]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg: Apply uncrustify changes
[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
2174 EFI_IFR_OP_HEADER *IfrOpHdr;\r
2175 EFI_IFR_ONE_OF *IfrOneOf;\r
2176 EFI_IFR_REF4 *IfrRef;\r
2177 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
2178 EFI_IFR_DEFAULT *IfrDefault;\r
2179 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
2180 EFI_IFR_CHECKBOX *IfrCheckBox;\r
2181 EFI_IFR_PASSWORD *IfrPassword;\r
2182 EFI_IFR_STRING *IfrString;\r
2183 EFI_IFR_DATE *IfrDate;\r
2184 EFI_IFR_TIME *IfrTime;\r
2185 IFR_DEFAULT_DATA DefaultData;\r
2186 IFR_DEFAULT_DATA *DefaultDataPtr;\r
2187 IFR_BLOCK_DATA *BlockData;\r
2188 CHAR16 *VarStoreName;\r
2189 UINTN NameSize;\r
2190 UINT16 VarWidth;\r
2191 UINT16 VarDefaultId;\r
2192 BOOLEAN FirstOneOfOption;\r
2193 BOOLEAN FirstOrderedList;\r
2194 LIST_ENTRY *LinkData;\r
2195 LIST_ENTRY *LinkDefault;\r
2196 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
2197 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
2198 EFI_VARSTORE_ID VarStoreId;\r
2199 UINT16 SmallestDefaultId;\r
2200 BOOLEAN SmallestIdFromFlag;\r
2201 BOOLEAN FromOtherDefaultOpcode;\r
2202 BOOLEAN QuestionReferBitField;\r
40ae09a2 2203\r
40ae09a2 2204 Status = EFI_SUCCESS;\r
40ae09a2
ED
2205 BlockData = NULL;\r
2206 DefaultDataPtr = NULL;\r
2207 FirstOneOfOption = FALSE;\r
22031c4f 2208 VarStoreId = 0;\r
9495c01e 2209 FirstOrderedList = FALSE;\r
a0b0cd73 2210 VarStoreName = NULL;\r
ef40f0f6 2211 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
1436aea4 2212 SmallestDefaultId = 0xFFFF;\r
22f63ff6 2213 FromOtherDefaultOpcode = FALSE;\r
1436aea4 2214 QuestionReferBitField = FALSE;\r
84f9a9ec
LG
2215\r
2216 //\r
2217 // Go through the form package to parse OpCode one by one.\r
2218 //\r
22031c4f 2219 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4 2220 PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;\r
22031c4f 2221 IfrOffset = PackageOffset;\r
aa75dfec 2222 while (IfrOffset < PackageLength) {\r
22031c4f
ED
2223 //\r
2224 // More than one form package found.\r
2225 //\r
2226 if (PackageOffset >= PackageHeader->Length) {\r
84f9a9ec 2227 //\r
1436aea4 2228 // Already found varstore for this request, break;\r
84f9a9ec 2229 //\r
22031c4f 2230 if (VarStoreId != 0) {\r
1436aea4 2231 VarStoreId = 0;\r
84f9a9ec
LG
2232 }\r
2233\r
1436aea4
MK
2234 //\r
2235 // Get next package header info.\r
2236 //\r
2237 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);\r
2238 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
2239 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(Package + IfrOffset);\r
2240 }\r
84f9a9ec 2241\r
1436aea4
MK
2242 IfrOpHdr = (EFI_IFR_OP_HEADER *)(Package + IfrOffset);\r
2243 switch (IfrOpHdr->OpCode) {\r
2244 case EFI_IFR_VARSTORE_OP:\r
84f9a9ec 2245 //\r
1436aea4 2246 // VarStore is found. Don't need to search any more.\r
84f9a9ec 2247 //\r
1436aea4
MK
2248 if (VarStoreId != 0) {\r
2249 break;\r
2250 }\r
84f9a9ec 2251\r
1436aea4 2252 IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;\r
cce6230f 2253\r
1436aea4
MK
2254 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);\r
2255 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
2256 if (VarStoreName == NULL) {\r
2257 Status = EFI_OUT_OF_RESOURCES;\r
2258 goto Done;\r
2259 }\r
cce6230f 2260\r
1436aea4 2261 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);\r
cce6230f 2262\r
1436aea4
MK
2263 if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
2264 //\r
2265 // Find the matched VarStore\r
2266 //\r
2267 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrVarStore->Guid);\r
2268 VarStorageData->Size = IfrVarStore->Size;\r
2269 VarStorageData->Name = VarStoreName;\r
2270 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
2271 VarStoreId = IfrVarStore->VarStoreId;\r
2272 } else {\r
2273 FreePool (VarStoreName);\r
2274 VarStoreName = NULL;\r
2275 }\r
2276\r
2277 break;\r
cce6230f 2278\r
1436aea4 2279 case EFI_IFR_VARSTORE_EFI_OP:\r
cce6230f 2280 //\r
1436aea4 2281 // VarStore is found. Don't need to search any more.\r
cce6230f 2282 //\r
1436aea4
MK
2283 if (VarStoreId != 0) {\r
2284 break;\r
2285 }\r
82e8c138 2286\r
1436aea4 2287 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;\r
82e8c138 2288\r
82e8c138 2289 //\r
1436aea4
MK
2290 // If the length is small than the structure, this is from old efi\r
2291 // varstore definition. Old efi varstore get config directly from\r
2292 // GetVariable function.\r
82e8c138 2293 //\r
1436aea4
MK
2294 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
2295 break;\r
2296 }\r
82e8c138 2297\r
1436aea4
MK
2298 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);\r
2299 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
2300 if (VarStoreName == NULL) {\r
2301 Status = EFI_OUT_OF_RESOURCES;\r
2302 goto Done;\r
2303 }\r
84f9a9ec 2304\r
1436aea4
MK
2305 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);\r
2306\r
2307 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
2308 //\r
2309 // Find the matched VarStore\r
2310 //\r
2311 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrEfiVarStore->Guid);\r
2312 VarStorageData->Size = IfrEfiVarStore->Size;\r
2313 VarStorageData->Name = VarStoreName;\r
2314 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
2315 VarStoreId = IfrEfiVarStore->VarStoreId;\r
2316 } else {\r
2317 FreePool (VarStoreName);\r
2318 VarStoreName = NULL;\r
2319 }\r
84f9a9ec 2320\r
e7fd76d1 2321 break;\r
e7fd76d1 2322\r
1436aea4
MK
2323 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
2324 //\r
2325 // VarStore is found. Don't need to search any more.\r
2326 //\r
2327 if (VarStoreId != 0) {\r
2328 break;\r
2329 }\r
f447734e 2330\r
1436aea4
MK
2331 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;\r
2332\r
2333 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
f447734e 2334 //\r
1436aea4 2335 // Find the matched VarStore\r
f447734e 2336 //\r
1436aea4
MK
2337 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrNameValueVarStore->Guid);\r
2338 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
2339 VarStoreId = IfrNameValueVarStore->VarStoreId;\r
f447734e 2340 }\r
e7fd76d1 2341\r
1436aea4 2342 break;\r
84f9a9ec 2343\r
1436aea4
MK
2344 case EFI_IFR_DEFAULTSTORE_OP:\r
2345 //\r
2346 // Add new the map between default id and default name.\r
2347 //\r
2348 DefaultDataPtr = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
2349 if (DefaultDataPtr == NULL) {\r
2350 Status = EFI_OUT_OF_RESOURCES;\r
2351 goto Done;\r
2352 }\r
2353\r
2354 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;\r
2355 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
2356 DefaultDataPtr = NULL;\r
84f9a9ec 2357 break;\r
37cd16ac 2358\r
1436aea4
MK
2359 case EFI_IFR_FORM_OP:\r
2360 case EFI_IFR_FORM_MAP_OP:\r
2361 //\r
2362 // No matched varstore is found and directly return.\r
2363 //\r
2364 if ( VarStoreId == 0) {\r
2365 Status = EFI_SUCCESS;\r
2366 goto Done;\r
2367 }\r
84f9a9ec 2368\r
1436aea4 2369 break;\r
f447734e 2370\r
1436aea4
MK
2371 case EFI_IFR_REF_OP:\r
2372 //\r
2373 // Ref question is not in IFR Form. This IFR form is not valid.\r
2374 //\r
2375 if ( VarStoreId == 0) {\r
2376 Status = EFI_INVALID_PARAMETER;\r
2377 goto Done;\r
2378 }\r
2379\r
2380 //\r
2381 // Check whether this question is for the requested varstore.\r
2382 //\r
2383 IfrRef = (EFI_IFR_REF4 *)IfrOpHdr;\r
2384 if (IfrRef->Question.VarStoreId != VarStoreId) {\r
f447734e
DB
2385 break;\r
2386 }\r
82e8c138 2387\r
1436aea4
MK
2388 VarWidth = (UINT16)(sizeof (EFI_HII_REF));\r
2389\r
2390 //\r
2391 // The BlockData may allocate by other opcode,need to clean.\r
2392 //\r
2393 if (BlockData != NULL) {\r
2394 BlockData = NULL;\r
2395 }\r
2396\r
2397 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2398 if (EFI_ERROR (Status)) {\r
2399 if (Status == EFI_NOT_FOUND) {\r
2400 //\r
2401 // The opcode is not required,exit and parse other opcode.\r
2402 //\r
2403 break;\r
2404 }\r
2405\r
2406 goto Done;\r
2407 }\r
2408\r
2409 break;\r
82e8c138 2410\r
1436aea4
MK
2411 case EFI_IFR_ONE_OF_OP:\r
2412 case EFI_IFR_NUMERIC_OP:\r
cf4c5a42 2413 //\r
1436aea4 2414 // Numeric and OneOf has the same opcode structure.\r
cf4c5a42 2415 //\r
1436aea4
MK
2416\r
2417 //\r
2418 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.\r
2419 //\r
2420 if (VarStoreId == 0) {\r
2421 Status = EFI_INVALID_PARAMETER;\r
2422 goto Done;\r
2423 }\r
2424\r
cf4c5a42 2425 //\r
1436aea4 2426 // Check whether this question is for the requested varstore.\r
cf4c5a42 2427 //\r
1436aea4
MK
2428 IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpHdr;\r
2429 if (IfrOneOf->Question.VarStoreId != VarStoreId) {\r
2430 break;\r
2431 }\r
2432\r
37cd16ac 2433 if (QuestionReferBitField) {\r
1436aea4 2434 VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
37cd16ac 2435 } else {\r
1436aea4
MK
2436 VarWidth = (UINT16)(1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
2437 }\r
37cd16ac 2438\r
1436aea4
MK
2439 //\r
2440 // The BlockData may allocate by other opcode,need to clean.\r
2441 //\r
2442 if (BlockData != NULL) {\r
2443 BlockData = NULL;\r
2444 }\r
37cd16ac 2445\r
1436aea4
MK
2446 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
2447 if (EFI_ERROR (Status)) {\r
2448 if (Status == EFI_NOT_FOUND) {\r
2449 //\r
2450 // The opcode is not required,exit and parse other opcode.\r
2451 //\r
37cd16ac 2452 break;\r
1436aea4 2453 }\r
37cd16ac 2454\r
1436aea4 2455 goto Done;\r
cf4c5a42 2456 }\r
1436aea4 2457\r
cf4c5a42 2458 //\r
1436aea4 2459 // when go to there,BlockData can't be NULLL.\r
d1102dba 2460 //\r
1436aea4 2461 ASSERT (BlockData != NULL);\r
84f9a9ec 2462\r
1436aea4
MK
2463 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
2464 //\r
2465 // Set this flag to TRUE for the first oneof option.\r
2466 //\r
2467 FirstOneOfOption = TRUE;\r
2468 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
2469 //\r
2470 // Numeric minimum value will be used as default value when no default is specified.\r
2471 //\r
2472 DefaultData.Type = DefaultValueFromDefault;\r
2473 if (QuestionReferBitField) {\r
2474 //\r
2475 // Since default value in bit field was stored as UINT32 type.\r
2476 //\r
2477 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
2478 } else {\r
2479 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
2480 case EFI_IFR_NUMERIC_SIZE_1:\r
2481 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
2482 break;\r
2483\r
2484 case EFI_IFR_NUMERIC_SIZE_2:\r
2485 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
2486 break;\r
2487\r
2488 case EFI_IFR_NUMERIC_SIZE_4:\r
2489 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
2490 break;\r
2491\r
2492 case EFI_IFR_NUMERIC_SIZE_8:\r
2493 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
2494 break;\r
2495\r
2496 default:\r
2497 Status = EFI_INVALID_PARAMETER;\r
2498 goto Done;\r
2499 }\r
2500 }\r
2501\r
2502 //\r
2503 // Set default value base on the DefaultId list get from IFR data.\r
2504 //\r
2505 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2506 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2507 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2508 InsertDefaultValue (BlockData, &DefaultData);\r
2509 }\r
2510 }\r
8567300a 2511\r
84f9a9ec 2512 break;\r
f447734e 2513\r
1436aea4
MK
2514 case EFI_IFR_ORDERED_LIST_OP:\r
2515 //\r
2516 // offset by question header\r
2517 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
2518 //\r
f447734e 2519\r
1436aea4
MK
2520 FirstOrderedList = TRUE;\r
2521 //\r
2522 // OrderedList question is not in IFR Form. This IFR form is not valid.\r
2523 //\r
2524 if (VarStoreId == 0) {\r
2525 Status = EFI_INVALID_PARAMETER;\r
2526 goto Done;\r
2527 }\r
2528\r
2529 //\r
2530 // Check whether this question is for the requested varstore.\r
2531 //\r
2532 IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpHdr;\r
2533 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {\r
2534 BlockData = NULL;\r
f447734e
DB
2535 break;\r
2536 }\r
84f9a9ec 2537\r
1436aea4
MK
2538 VarWidth = IfrOrderedList->MaxContainers;\r
2539\r
2540 //\r
2541 // The BlockData may allocate by other opcode,need to clean.\r
2542 //\r
2543 if (BlockData != NULL) {\r
2544 BlockData = NULL;\r
2545 }\r
2546\r
2547 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2548 if (EFI_ERROR (Status)) {\r
2549 if (Status == EFI_NOT_FOUND) {\r
2550 //\r
2551 // The opcode is not required,exit and parse other opcode.\r
2552 //\r
2553 break;\r
2554 }\r
2555\r
2556 goto Done;\r
2557 }\r
84f9a9ec 2558\r
84f9a9ec 2559 break;\r
f447734e 2560\r
1436aea4
MK
2561 case EFI_IFR_CHECKBOX_OP:\r
2562 //\r
2563 // EFI_IFR_DEFAULT_OP\r
2564 // offset by question header\r
2565 // width is 1 sizeof (BOOLEAN)\r
2566 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
2567 // value by DefaultOption\r
2568 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
2569 //\r
f447734e 2570\r
1436aea4
MK
2571 //\r
2572 // CheckBox question is not in IFR Form. This IFR form is not valid.\r
2573 //\r
2574 if (VarStoreId == 0) {\r
2575 Status = EFI_INVALID_PARAMETER;\r
2576 goto Done;\r
f447734e 2577 }\r
84f9a9ec 2578\r
1436aea4
MK
2579 //\r
2580 // Check whether this question is for the requested varstore.\r
2581 //\r
2582 IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;\r
2583 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {\r
2584 break;\r
2585 }\r
84f9a9ec 2586\r
1436aea4 2587 VarWidth = (UINT16)sizeof (BOOLEAN);\r
22f63ff6 2588\r
84f9a9ec 2589 //\r
1436aea4 2590 // The BlockData may allocate by other opcode,need to clean.\r
84f9a9ec 2591 //\r
1436aea4
MK
2592 if (BlockData != NULL) {\r
2593 BlockData = NULL;\r
2594 }\r
2595\r
37cd16ac 2596 if (QuestionReferBitField) {\r
1436aea4
MK
2597 VarWidth = 1;\r
2598 }\r
2599\r
2600 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
2601 if (EFI_ERROR (Status)) {\r
2602 if (Status == EFI_NOT_FOUND) {\r
2603 //\r
2604 // The opcode is not required,exit and parse other opcode.\r
2605 //\r
2606 break;\r
2607 }\r
2608\r
2609 goto Done;\r
37cd16ac 2610 }\r
22f63ff6 2611\r
1436aea4
MK
2612 //\r
2613 // when go to there,BlockData can't be NULLL.\r
2614 //\r
2615 ASSERT (BlockData != NULL);\r
2616\r
2617 SmallestIdFromFlag = FALSE;\r
2618\r
2619 //\r
2620 // Add default value for standard ID by CheckBox Flag\r
2621 //\r
2622 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2623 //\r
2624 // Prepare new DefaultValue\r
2625 //\r
2626 DefaultData.DefaultId = VarDefaultId;\r
2627 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
22f63ff6 2628 //\r
1436aea4 2629 // When flag is set, default value is TRUE.\r
22f63ff6 2630 //\r
1436aea4
MK
2631 DefaultData.Type = DefaultValueFromFlag;\r
2632 if (QuestionReferBitField) {\r
2633 DefaultData.Value.u32 = TRUE;\r
2634 } else {\r
2635 DefaultData.Value.b = TRUE;\r
2636 }\r
2637\r
2638 InsertDefaultValue (BlockData, &DefaultData);\r
2639\r
2640 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2641 //\r
2642 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2643 //\r
2644 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2645 SmallestIdFromFlag = TRUE;\r
2646 }\r
22f63ff6 2647 }\r
84f9a9ec 2648\r
84f9a9ec 2649 //\r
1436aea4 2650 // Add default value for Manufacture ID by CheckBox Flag\r
84f9a9ec 2651 //\r
1436aea4
MK
2652 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2653 //\r
2654 // Prepare new DefaultValue\r
2655 //\r
2656 DefaultData.DefaultId = VarDefaultId;\r
2657 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
2658 //\r
2659 // When flag is set, default value is TRUE.\r
2660 //\r
2661 DefaultData.Type = DefaultValueFromFlag;\r
2662 if (QuestionReferBitField) {\r
2663 DefaultData.Value.u32 = TRUE;\r
2664 } else {\r
2665 DefaultData.Value.b = TRUE;\r
2666 }\r
2667\r
2668 InsertDefaultValue (BlockData, &DefaultData);\r
2669\r
2670 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2671 //\r
2672 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2673 //\r
2674 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2675 SmallestIdFromFlag = TRUE;\r
2676 }\r
37cd16ac 2677 }\r
22f63ff6 2678\r
1436aea4
MK
2679 if (SmallestIdFromFlag) {\r
2680 //\r
2681 // 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
2682 //\r
2683 DefaultData.Type = DefaultValueFromOtherDefault;\r
2684 if (QuestionReferBitField) {\r
2685 DefaultData.Value.u32 = TRUE;\r
2686 } else {\r
2687 DefaultData.Value.b = TRUE;\r
2688 }\r
2689\r
2690 //\r
2691 // Set default value for all the default id in the DefaultId list.\r
2692 //\r
2693 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2694 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2695 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2696 InsertDefaultValue (BlockData, &DefaultData);\r
2697 }\r
2698 } else {\r
2699 //\r
2700 // When flag is not set, default value is FASLE.\r
2701 //\r
2702 DefaultData.Type = DefaultValueFromDefault;\r
2703 if (QuestionReferBitField) {\r
2704 DefaultData.Value.u32 = FALSE;\r
2705 } else {\r
2706 DefaultData.Value.b = FALSE;\r
2707 }\r
2708\r
22f63ff6 2709 //\r
1436aea4 2710 // Set default value for all the default id in the DefaultId list.\r
22f63ff6 2711 //\r
1436aea4
MK
2712 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2713 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2714 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2715 InsertDefaultValue (BlockData, &DefaultData);\r
2716 }\r
22f63ff6 2717 }\r
1436aea4
MK
2718\r
2719 break;\r
2720\r
2721 case EFI_IFR_DATE_OP:\r
22f63ff6 2722 //\r
1436aea4
MK
2723 // offset by question header\r
2724 // width MaxSize * sizeof (CHAR16)\r
2725 // no default value, only block array\r
22f63ff6 2726 //\r
1436aea4 2727\r
22f63ff6 2728 //\r
1436aea4 2729 // Date question is not in IFR Form. This IFR form is not valid.\r
22f63ff6 2730 //\r
1436aea4
MK
2731 if (VarStoreId == 0) {\r
2732 Status = EFI_INVALID_PARAMETER;\r
2733 goto Done;\r
22f63ff6 2734 }\r
1436aea4 2735\r
84f9a9ec 2736 //\r
1436aea4 2737 // Check whether this question is for the requested varstore.\r
84f9a9ec 2738 //\r
1436aea4
MK
2739 IfrDate = (EFI_IFR_DATE *)IfrOpHdr;\r
2740 if (IfrDate->Question.VarStoreId != VarStoreId) {\r
2741 break;\r
37cd16ac 2742 }\r
1436aea4 2743\r
22f63ff6 2744 //\r
1436aea4 2745 // The BlockData may allocate by other opcode,need to clean.\r
22f63ff6 2746 //\r
1436aea4
MK
2747 if (BlockData != NULL) {\r
2748 BlockData = NULL;\r
22f63ff6 2749 }\r
84f9a9ec 2750\r
1436aea4
MK
2751 VarWidth = (UINT16)sizeof (EFI_HII_DATE);\r
2752 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2753 if (EFI_ERROR (Status)) {\r
2754 if (Status == EFI_NOT_FOUND) {\r
2755 //\r
2756 // The opcode is not required,exit and parse other opcode.\r
2757 //\r
2758 break;\r
2759 }\r
2760\r
2761 goto Done;\r
2762 }\r
d9bbabfd 2763\r
d9bbabfd 2764 break;\r
d9bbabfd 2765\r
1436aea4
MK
2766 case EFI_IFR_TIME_OP:\r
2767 //\r
2768 // offset by question header\r
2769 // width MaxSize * sizeof (CHAR16)\r
2770 // no default value, only block array\r
2771 //\r
f447734e 2772\r
1436aea4
MK
2773 //\r
2774 // Time question is not in IFR Form. This IFR form is not valid.\r
2775 //\r
2776 if (VarStoreId == 0) {\r
2777 Status = EFI_INVALID_PARAMETER;\r
2778 goto Done;\r
f447734e 2779 }\r
d9bbabfd 2780\r
1436aea4
MK
2781 //\r
2782 // Check whether this question is for the requested varstore.\r
2783 //\r
2784 IfrTime = (EFI_IFR_TIME *)IfrOpHdr;\r
2785 if (IfrTime->Question.VarStoreId != VarStoreId) {\r
2786 break;\r
2787 }\r
d9bbabfd 2788\r
1436aea4
MK
2789 //\r
2790 // The BlockData may allocate by other opcode,need to clean.\r
2791 //\r
2792 if (BlockData != NULL) {\r
2793 BlockData = NULL;\r
2794 }\r
d9bbabfd 2795\r
1436aea4
MK
2796 VarWidth = (UINT16)sizeof (EFI_HII_TIME);\r
2797 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2798 if (EFI_ERROR (Status)) {\r
2799 if (Status == EFI_NOT_FOUND) {\r
2800 //\r
2801 // The opcode is not required,exit and parse other opcode.\r
2802 //\r
2803 break;\r
2804 }\r
f447734e 2805\r
1436aea4 2806 goto Done;\r
f447734e 2807 }\r
d9bbabfd 2808\r
84f9a9ec 2809 break;\r
84f9a9ec 2810\r
1436aea4
MK
2811 case EFI_IFR_STRING_OP:\r
2812 //\r
2813 // offset by question header\r
2814 // width MaxSize * sizeof (CHAR16)\r
2815 // no default value, only block array\r
2816 //\r
f447734e 2817\r
1436aea4
MK
2818 //\r
2819 // String question is not in IFR Form. This IFR form is not valid.\r
2820 //\r
2821 if (VarStoreId == 0) {\r
2822 Status = EFI_INVALID_PARAMETER;\r
2823 goto Done;\r
f447734e 2824 }\r
84f9a9ec 2825\r
1436aea4
MK
2826 //\r
2827 // Check whether this question is for the requested varstore.\r
2828 //\r
2829 IfrString = (EFI_IFR_STRING *)IfrOpHdr;\r
2830 if (IfrString->Question.VarStoreId != VarStoreId) {\r
2831 break;\r
2832 }\r
84f9a9ec 2833\r
1436aea4
MK
2834 //\r
2835 // The BlockData may allocate by other opcode,need to clean.\r
2836 //\r
2837 if (BlockData != NULL) {\r
2838 BlockData = NULL;\r
2839 }\r
84f9a9ec 2840\r
1436aea4
MK
2841 VarWidth = (UINT16)(IfrString->MaxSize * sizeof (UINT16));\r
2842 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2843 if (EFI_ERROR (Status)) {\r
2844 if (Status == EFI_NOT_FOUND) {\r
2845 //\r
2846 // The opcode is not required,exit and parse other opcode.\r
2847 //\r
2848 break;\r
2849 }\r
f447734e 2850\r
1436aea4 2851 goto Done;\r
f447734e 2852 }\r
84f9a9ec 2853\r
84f9a9ec 2854 break;\r
82e8c138 2855\r
1436aea4
MK
2856 case EFI_IFR_PASSWORD_OP:\r
2857 //\r
2858 // offset by question header\r
2859 // width MaxSize * sizeof (CHAR16)\r
2860 // no default value, only block array\r
2861 //\r
9495c01e 2862\r
84f9a9ec 2863 //\r
1436aea4 2864 // Password question is not in IFR Form. This IFR form is not valid.\r
84f9a9ec 2865 //\r
1436aea4 2866 if (VarStoreId == 0) {\r
84f9a9ec
LG
2867 Status = EFI_INVALID_PARAMETER;\r
2868 goto Done;\r
2869 }\r
ff28420b 2870\r
84f9a9ec 2871 //\r
1436aea4 2872 // Check whether this question is for the requested varstore.\r
84f9a9ec 2873 //\r
1436aea4
MK
2874 IfrPassword = (EFI_IFR_PASSWORD *)IfrOpHdr;\r
2875 if (IfrPassword->Question.VarStoreId != VarStoreId) {\r
ff28420b
LG
2876 break;\r
2877 }\r
1436aea4 2878\r
ff28420b 2879 //\r
1436aea4 2880 // The BlockData may allocate by other opcode,need to clean.\r
ff28420b 2881 //\r
1436aea4
MK
2882 if (BlockData != NULL) {\r
2883 BlockData = NULL;\r
2884 }\r
2885\r
2886 VarWidth = (UINT16)(IfrPassword->MaxSize * sizeof (UINT16));\r
2887 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
2888 if (EFI_ERROR (Status)) {\r
2889 if (Status == EFI_NOT_FOUND) {\r
2890 //\r
2891 // The opcode is not required,exit and parse other opcode.\r
2892 //\r
2893 break;\r
2894 }\r
2895\r
ff28420b
LG
2896 goto Done;\r
2897 }\r
1436aea4 2898\r
ff28420b 2899 //\r
1436aea4 2900 // No default value for string.\r
ff28420b 2901 //\r
1436aea4 2902 BlockData = NULL;\r
84f9a9ec 2903 break;\r
84f9a9ec 2904\r
1436aea4 2905 case EFI_IFR_ONE_OF_OPTION_OP:\r
cf4c5a42 2906 //\r
1436aea4 2907 // No matched block data is ignored.\r
cf4c5a42 2908 //\r
1436aea4
MK
2909 if ((BlockData == NULL) || (BlockData->Scope == 0)) {\r
2910 break;\r
2911 }\r
22f63ff6 2912\r
1436aea4
MK
2913 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;\r
2914 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2915 if (!FirstOrderedList) {\r
2916 break;\r
2917 }\r
d1102dba 2918\r
1436aea4
MK
2919 //\r
2920 // Get ordered list option data type.\r
2921 //\r
2922 if ((IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN)) {\r
2923 VarWidth = 1;\r
2924 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
2925 VarWidth = 2;\r
2926 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
2927 VarWidth = 4;\r
2928 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
2929 VarWidth = 8;\r
2930 } else {\r
22f63ff6 2931 //\r
1436aea4 2932 // Invalid ordered list option data type.\r
22f63ff6 2933 //\r
1436aea4
MK
2934 Status = EFI_INVALID_PARAMETER;\r
2935 if (BlockData->Name != NULL) {\r
2936 FreePool (BlockData->Name);\r
2937 }\r
2938\r
2939 FreePool (BlockData);\r
2940 goto Done;\r
22f63ff6 2941 }\r
1436aea4
MK
2942\r
2943 //\r
2944 // Calculate Ordered list QuestionId width.\r
2945 //\r
2946 BlockData->Width = (UINT16)(BlockData->Width * VarWidth);\r
2947 //\r
2948 // Check whether this question is in requested block array.\r
2949 //\r
2950 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
22f63ff6 2951 //\r
1436aea4 2952 // This question is not in the requested string. Skip it.\r
22f63ff6 2953 //\r
1436aea4
MK
2954 if (BlockData->Name != NULL) {\r
2955 FreePool (BlockData->Name);\r
2956 }\r
2957\r
2958 FreePool (BlockData);\r
2959 BlockData = NULL;\r
2960 break;\r
2961 }\r
2962\r
2963 //\r
2964 // Check this var question is in the var storage\r
2965 //\r
2966 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
2967 Status = EFI_INVALID_PARAMETER;\r
2968 FreePool (BlockData);\r
2969 goto Done;\r
22f63ff6 2970 }\r
1436aea4
MK
2971\r
2972 //\r
2973 // Add Block Data into VarStorageData BlockEntry\r
2974 //\r
2975 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
2976\r
2977 FirstOrderedList = FALSE;\r
2978\r
2979 break;\r
22f63ff6
DB
2980 }\r
2981\r
1436aea4
MK
2982 //\r
2983 // 1. Set default value for OneOf option when flag field has default attribute.\r
2984 // And set the default value with the smallest default id for other default id in the DefaultId list.\r
2985 //\r
2986 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
2987 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))\r
2988 {\r
22f63ff6 2989 //\r
1436aea4
MK
2990 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.\r
2991 // The first oneof option value will be used as default value when no default value is specified.\r
22f63ff6 2992 //\r
1436aea4
MK
2993 FirstOneOfOption = FALSE;\r
2994\r
2995 SmallestIdFromFlag = FALSE;\r
2996\r
2997 // Prepare new DefaultValue\r
2998 //\r
2999 DefaultData.Type = DefaultValueFromFlag;\r
3000 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
3001 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
3002 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
3003 InsertDefaultValue (BlockData, &DefaultData);\r
3004 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
3005 //\r
3006 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
3007 //\r
3008 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
3009 SmallestIdFromFlag = TRUE;\r
3010 }\r
3011 }\r
3012\r
3013 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
3014 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
3015 InsertDefaultValue (BlockData, &DefaultData);\r
3016 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
3017 //\r
3018 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
3019 //\r
3020 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
3021 SmallestIdFromFlag = TRUE;\r
3022 }\r
3023 }\r
3024\r
3025 if (SmallestIdFromFlag) {\r
3026 //\r
3027 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.\r
3028 //\r
3029 DefaultData.Type = DefaultValueFromOtherDefault;\r
3030 //\r
3031 // Set default value for other default id in the DefaultId list.\r
3032 //\r
3033 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
3034 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
3035 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
3036 InsertDefaultValue (BlockData, &DefaultData);\r
3037 }\r
3038 }\r
3039 }\r
3040\r
3041 //\r
3042 // 2. Set as the default value when this is the first option.\r
3043 // The first oneof option value will be used as default value when no default value is specified.\r
3044 //\r
3045 if (FirstOneOfOption) {\r
3046 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.\r
3047 FirstOneOfOption = FALSE;\r
3048\r
22f63ff6 3049 //\r
1436aea4 3050 // Prepare new DefaultValue\r
22f63ff6 3051 //\r
1436aea4
MK
3052 DefaultData.Type = DefaultValueFromDefault;\r
3053 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
22f63ff6 3054 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
1436aea4
MK
3055 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
3056 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
22f63ff6
DB
3057 InsertDefaultValue (BlockData, &DefaultData);\r
3058 }\r
84f9a9ec 3059 }\r
82e8c138 3060\r
1436aea4 3061 break;\r
d1102dba 3062\r
1436aea4 3063 case EFI_IFR_DEFAULT_OP:\r
84f9a9ec 3064 //\r
1436aea4 3065 // Update Current BlockData to the default value.\r
d1102dba 3066 //\r
1436aea4
MK
3067 if ((BlockData == NULL) || (BlockData->Scope == 0)) {\r
3068 //\r
3069 // No matched block data is ignored.\r
3070 //\r
3071 break;\r
82e8c138 3072 }\r
84f9a9ec 3073\r
84f9a9ec 3074 //\r
1436aea4 3075 // Get the DefaultId\r
84f9a9ec 3076 //\r
1436aea4
MK
3077 IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;\r
3078 VarDefaultId = IfrDefault->DefaultId;\r
3079 //\r
3080 // Prepare new DefaultValue\r
3081 //\r
3082 DefaultData.Type = DefaultValueFromOpcode;\r
3083 DefaultData.DefaultId = VarDefaultId;\r
3084 if (QuestionReferBitField) {\r
3085 CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));\r
3086 } else {\r
3087 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
3088 }\r
84f9a9ec 3089\r
1436aea4
MK
3090 // If the value field is expression, set the cleaned flag.\r
3091 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
3092 DefaultData.Cleaned = TRUE;\r
3093 }\r
82e8c138 3094\r
1436aea4
MK
3095 //\r
3096 // Add DefaultValue into current BlockData\r
3097 //\r
3098 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 3099\r
1436aea4
MK
3100 //\r
3101 // Set default value for other default id in the DefaultId list.\r
3102 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.\r
3103 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.\r
3104 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.\r
3105 //\r
3106 if ((SmallestDefaultId > VarDefaultId) || ((SmallestDefaultId == VarDefaultId) && !FromOtherDefaultOpcode)) {\r
3107 FromOtherDefaultOpcode = TRUE;\r
3108 SmallestDefaultId = VarDefaultId;\r
3109 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
3110 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
3111 if (DefaultDataPtr->DefaultId != DefaultData.DefaultId) {\r
3112 DefaultData.Type = DefaultValueFromOtherDefault;\r
3113 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
3114 InsertDefaultValue (BlockData, &DefaultData);\r
3115 }\r
22f63ff6
DB
3116 }\r
3117 }\r
22f63ff6 3118\r
1436aea4
MK
3119 //\r
3120 // After insert the default value, reset the cleaned value for next\r
3121 // time used. If not set here, need to set the value before every time.\r
3122 // use it.\r
3123 //\r
3124 DefaultData.Cleaned = FALSE;\r
3125 break;\r
82e8c138 3126\r
1436aea4
MK
3127 case EFI_IFR_END_OP:\r
3128 //\r
3129 // End Opcode is for Var question.\r
3130 //\r
3131 QuestionReferBitField = FALSE;\r
3132 if (BlockData != NULL) {\r
3133 if (BlockData->Scope > 0) {\r
3134 BlockData->Scope--;\r
3135 }\r
3136\r
3137 if (BlockData->Scope == 0) {\r
3138 BlockData = NULL;\r
3139 //\r
3140 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.\r
3141 //\r
3142 SmallestDefaultId = 0xFFFF;\r
3143 FromOtherDefaultOpcode = FALSE;\r
3144 }\r
7248790e 3145 }\r
1436aea4
MK
3146\r
3147 break;\r
3148\r
3149 case EFI_IFR_GUID_OP:\r
3150 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
3151 QuestionReferBitField = TRUE;\r
7248790e 3152 }\r
7248790e 3153\r
1436aea4 3154 break;\r
82e8c138 3155\r
1436aea4
MK
3156 default:\r
3157 if (BlockData != NULL) {\r
3158 if (BlockData->Scope > 0) {\r
3159 BlockData->Scope = (UINT8)(BlockData->Scope + IfrOpHdr->Scope);\r
3160 }\r
37cd16ac 3161\r
1436aea4
MK
3162 if (BlockData->Scope == 0) {\r
3163 BlockData = NULL;\r
3164 }\r
7248790e
ED
3165 }\r
3166\r
1436aea4 3167 break;\r
84f9a9ec
LG
3168 }\r
3169\r
22031c4f
ED
3170 IfrOffset += IfrOpHdr->Length;\r
3171 PackageOffset += IfrOpHdr->Length;\r
84f9a9ec
LG
3172 }\r
3173\r
f447734e 3174 //\r
1436aea4
MK
3175 // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,\r
3176 // so set the Status to EFI_SUCCESS.\r
f447734e 3177 //\r
1436aea4 3178 if (Status == EFI_NOT_FOUND) {\r
f447734e
DB
3179 Status = EFI_SUCCESS;\r
3180 }\r
3181\r
84f9a9ec 3182Done:\r
ef40f0f6
ED
3183 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
3184 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
3185 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
3186 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1436aea4 3187 LinkDefault = LinkDefault->ForwardLink;\r
ef40f0f6
ED
3188 if (DefaultDataPtr->Cleaned == TRUE) {\r
3189 RemoveEntryList (&DefaultDataPtr->Entry);\r
3190 FreePool (DefaultDataPtr);\r
3191 }\r
3192 }\r
3193 }\r
3194\r
82e8c138 3195 return Status;\r
84f9a9ec
LG
3196}\r
3197\r
3198/**\r
82e8c138 3199 parse the configrequest string, get the elements.\r
84f9a9ec 3200\r
82e8c138
ED
3201 @param ConfigRequest The input configrequest string.\r
3202 @param Progress Return the progress data.\r
3203\r
3204 @retval Block data pointer.\r
3205**/\r
3206IFR_BLOCK_DATA *\r
3207GetBlockElement (\r
1436aea4
MK
3208 IN EFI_STRING ConfigRequest,\r
3209 OUT EFI_STRING *Progress\r
82e8c138
ED
3210 )\r
3211{\r
1436aea4
MK
3212 EFI_STRING StringPtr;\r
3213 IFR_BLOCK_DATA *BlockData;\r
3214 IFR_BLOCK_DATA *RequestBlockArray;\r
3215 EFI_STATUS Status;\r
3216 UINT8 *TmpBuffer;\r
3217 UINT16 Offset;\r
3218 UINT16 Width;\r
3219 LIST_ENTRY *Link;\r
3220 IFR_BLOCK_DATA *NextBlockData;\r
3221 UINTN Length;\r
82e8c138 3222\r
4e1005ec
ED
3223 TmpBuffer = NULL;\r
3224\r
82e8c138
ED
3225 //\r
3226 // Init RequestBlockArray\r
3227 //\r
1436aea4 3228 RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
82e8c138
ED
3229 if (RequestBlockArray == NULL) {\r
3230 goto Done;\r
3231 }\r
1436aea4 3232\r
82e8c138
ED
3233 InitializeListHead (&RequestBlockArray->Entry);\r
3234\r
3235 //\r
3236 // Get the request Block array from the request string\r
3237 // Offset and Width\r
3238 //\r
3239\r
3240 //\r
3241 // Parse each <RequestElement> if exists\r
3242 // Only <BlockName> format is supported by this help function.\r
3243 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
3244 //\r
3245 StringPtr = ConfigRequest;\r
3246 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
3247 //\r
3248 // Skip the OFFSET string\r
3249 //\r
1436aea4 3250 *Progress = StringPtr;\r
82e8c138
ED
3251 StringPtr += StrLen (L"&OFFSET=");\r
3252 //\r
3253 // Get Offset\r
3254 //\r
3255 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3256 if (EFI_ERROR (Status)) {\r
3257 goto Done;\r
3258 }\r
1436aea4 3259\r
82e8c138
ED
3260 Offset = 0;\r
3261 CopyMem (\r
3262 &Offset,\r
3263 TmpBuffer,\r
3264 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
3265 );\r
3266 FreePool (TmpBuffer);\r
3267\r
3268 StringPtr += Length;\r
3269 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3270 goto Done;\r
3271 }\r
1436aea4 3272\r
82e8c138
ED
3273 StringPtr += StrLen (L"&WIDTH=");\r
3274\r
3275 //\r
3276 // Get Width\r
3277 //\r
3278 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3279 if (EFI_ERROR (Status)) {\r
3280 goto Done;\r
3281 }\r
1436aea4 3282\r
82e8c138
ED
3283 Width = 0;\r
3284 CopyMem (\r
3285 &Width,\r
3286 TmpBuffer,\r
3287 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
3288 );\r
3289 FreePool (TmpBuffer);\r
3290\r
3291 StringPtr += Length;\r
1436aea4 3292 if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
82e8c138
ED
3293 goto Done;\r
3294 }\r
d1102dba 3295\r
82e8c138
ED
3296 //\r
3297 // Set Block Data\r
3298 //\r
1436aea4 3299 BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
82e8c138
ED
3300 if (BlockData == NULL) {\r
3301 goto Done;\r
3302 }\r
1436aea4 3303\r
82e8c138
ED
3304 BlockData->Offset = Offset;\r
3305 BlockData->Width = Width;\r
3306 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
3307\r
3308 //\r
3309 // Skip &VALUE string if &VALUE does exists.\r
3310 //\r
3311 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
3312 StringPtr += StrLen (L"&VALUE=");\r
3313\r
3314 //\r
3315 // Get Value\r
3316 //\r
3317 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3318 if (EFI_ERROR (Status)) {\r
3319 goto Done;\r
3320 }\r
1436aea4 3321\r
a0b0cd73 3322 FreePool (TmpBuffer);\r
82e8c138 3323 StringPtr += Length;\r
1436aea4 3324 if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
82e8c138
ED
3325 goto Done;\r
3326 }\r
3327 }\r
1436aea4 3328\r
82e8c138 3329 //\r
d1102dba 3330 // If '\0', parsing is finished.\r
82e8c138
ED
3331 //\r
3332 if (*StringPtr == 0) {\r
3333 break;\r
3334 }\r
3335 }\r
3336\r
3337 //\r
3338 // Merge the requested block data.\r
3339 //\r
3340 Link = RequestBlockArray->Entry.ForwardLink;\r
3341 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
1436aea4 3342 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
82e8c138
ED
3343 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
3344 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
3345 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1436aea4 3346 BlockData->Width = (UINT16)(NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
82e8c138 3347 }\r
1436aea4 3348\r
82e8c138
ED
3349 RemoveEntryList (Link->ForwardLink);\r
3350 FreePool (NextBlockData);\r
3351 continue;\r
3352 }\r
1436aea4 3353\r
82e8c138
ED
3354 Link = Link->ForwardLink;\r
3355 }\r
3356\r
3357 return RequestBlockArray;\r
3358\r
3359Done:\r
3360 if (RequestBlockArray != NULL) {\r
3361 //\r
3362 // Free Link Array RequestBlockArray\r
3363 //\r
3364 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3365 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3366 RemoveEntryList (&BlockData->Entry);\r
3367 FreePool (BlockData);\r
3368 }\r
3369\r
3370 FreePool (RequestBlockArray);\r
3371 }\r
3372\r
3373 return NULL;\r
3374}\r
3375\r
3376/**\r
3377 parse the configrequest string, get the elements.\r
3378\r
3379 @param ConfigRequest The input config request string.\r
3380 @param Progress Return the progress data.\r
3381\r
3382 @retval return data block array.\r
3383**/\r
3384IFR_BLOCK_DATA *\r
3385GetNameElement (\r
1436aea4
MK
3386 IN EFI_STRING ConfigRequest,\r
3387 OUT EFI_STRING *Progress\r
82e8c138
ED
3388 )\r
3389{\r
1436aea4
MK
3390 EFI_STRING StringPtr;\r
3391 EFI_STRING NextTag;\r
3392 IFR_BLOCK_DATA *BlockData;\r
3393 IFR_BLOCK_DATA *RequestBlockArray;\r
3394 BOOLEAN HasValue;\r
82e8c138
ED
3395\r
3396 StringPtr = ConfigRequest;\r
3397\r
3398 //\r
3399 // Init RequestBlockArray\r
3400 //\r
1436aea4 3401 RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
82e8c138
ED
3402 if (RequestBlockArray == NULL) {\r
3403 goto Done;\r
3404 }\r
1436aea4 3405\r
82e8c138
ED
3406 InitializeListHead (&RequestBlockArray->Entry);\r
3407\r
3408 //\r
3409 // Get the request Block array from the request string\r
3410 //\r
3411\r
3412 //\r
3413 // Parse each <RequestElement> if exists\r
3414 // Only <BlockName> format is supported by this help function.\r
3415 // <BlockName> ::= &'Name***=***\r
3416 //\r
3417 while (StringPtr != NULL && *StringPtr == L'&') {\r
1436aea4 3418 *Progress = StringPtr;\r
82e8c138
ED
3419 //\r
3420 // Skip the L"&" string\r
3421 //\r
3422 StringPtr += 1;\r
3423\r
3424 HasValue = FALSE;\r
3425 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
3426 *NextTag = L'\0';\r
3427 HasValue = TRUE;\r
3428 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
3429 *NextTag = L'\0';\r
3430 }\r
3431\r
3432 //\r
3433 // Set Block Data\r
3434 //\r
1436aea4 3435 BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
82e8c138
ED
3436 if (BlockData == NULL) {\r
3437 goto Done;\r
3438 }\r
3439\r
3440 //\r
3441 // Get Name\r
3442 //\r
1436aea4 3443 BlockData->Name = AllocateCopyPool (StrSize (StringPtr), StringPtr);\r
82e8c138
ED
3444 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
3445\r
3446 if (HasValue) {\r
3447 //\r
3448 // If has value, skip the value.\r
d1102dba 3449 //\r
82e8c138
ED
3450 StringPtr = NextTag + 1;\r
3451 *NextTag = L'=';\r
3452 StringPtr = StrStr (StringPtr, L"&");\r
3453 } else if (NextTag != NULL) {\r
3454 //\r
3455 // restore the '&' text.\r
3456 //\r
3457 StringPtr = NextTag;\r
3458 *NextTag = L'&';\r
3459 }\r
3460 }\r
3461\r
3462 return RequestBlockArray;\r
3463\r
3464Done:\r
3465 if (RequestBlockArray != NULL) {\r
3466 //\r
3467 // Free Link Array RequestBlockArray\r
3468 //\r
3469 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3470 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3471 RemoveEntryList (&BlockData->Entry);\r
3472 if (BlockData->Name != NULL) {\r
3473 FreePool (BlockData->Name);\r
3474 }\r
1436aea4 3475\r
82e8c138
ED
3476 FreePool (BlockData);\r
3477 }\r
3478\r
3479 FreePool (RequestBlockArray);\r
3480 }\r
3481\r
3482 return NULL;\r
3483}\r
3484\r
3485/**\r
3486 Generate ConfigRequest string base on the varstore info.\r
3487\r
3488 @param ConfigHdr The config header for this varstore.\r
3489 @param VarStorageData The varstore info.\r
3490 @param Status Return Status.\r
3491 @param ConfigRequest The ConfigRequest info may be return.\r
3492\r
3493 @retval TRUE Need to continue\r
3494 @retval Others NO need to continue or error occur.\r
3495**/\r
3496BOOLEAN\r
3497GenerateConfigRequest (\r
1436aea4
MK
3498 IN CHAR16 *ConfigHdr,\r
3499 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3500 OUT EFI_STATUS *Status,\r
3501 IN OUT EFI_STRING *ConfigRequest\r
82e8c138
ED
3502 )\r
3503{\r
1436aea4
MK
3504 BOOLEAN DataExist;\r
3505 UINTN Length;\r
3506 LIST_ENTRY *Link;\r
3507 CHAR16 *FullConfigRequest;\r
3508 CHAR16 *StringPtr;\r
3509 IFR_BLOCK_DATA *BlockData;\r
82e8c138
ED
3510\r
3511 //\r
3512 // Append VarStorageData BlockEntry into *Request string\r
3513 // Now support only one varstore in a form package.\r
3514 //\r
d1102dba 3515\r
82e8c138
ED
3516 //\r
3517 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
3518 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
3519 //\r
d1102dba 3520\r
82e8c138 3521 //\r
d1102dba 3522 // Compute the length of the entire request starting with <ConfigHdr> and a\r
82e8c138
ED
3523 // Null-terminator\r
3524 //\r
3525 DataExist = FALSE;\r
3526 Length = StrLen (ConfigHdr) + 1;\r
3527\r
3528 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
3529 DataExist = TRUE;\r
3530 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3531 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3532 //\r
3533 // Add <BlockName> length for each Name\r
3534 //\r
d1102dba 3535 // <BlockName> ::= &Name1&Name2&...\r
82e8c138
ED
3536 // |1| StrLen(Name1)\r
3537 //\r
3538 Length = Length + (1 + StrLen (BlockData->Name));\r
3539 } else {\r
3540 //\r
3541 // Add <BlockName> length for each Offset/Width pair\r
3542 //\r
3543 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
3544 // | 8 | 4 | 7 | 4 |\r
3545 //\r
3546 Length = Length + (8 + 4 + 7 + 4);\r
3547 }\r
3548 }\r
1436aea4 3549\r
82e8c138
ED
3550 //\r
3551 // No any request block data is found. The request string can't be constructed.\r
3552 //\r
3553 if (!DataExist) {\r
3554 *Status = EFI_SUCCESS;\r
3555 return FALSE;\r
3556 }\r
3557\r
3558 //\r
3559 // Allocate buffer for the entire <ConfigRequest>\r
3560 //\r
3561 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
3562 if (FullConfigRequest == NULL) {\r
3563 *Status = EFI_OUT_OF_RESOURCES;\r
3564 return FALSE;\r
3565 }\r
1436aea4 3566\r
82e8c138
ED
3567 StringPtr = FullConfigRequest;\r
3568\r
3569 //\r
3570 // Start with <ConfigHdr>\r
3571 //\r
5ad66ec6 3572 StrCpyS (StringPtr, Length, ConfigHdr);\r
82e8c138
ED
3573 StringPtr += StrLen (StringPtr);\r
3574\r
3575 //\r
3576 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
3577 //\r
3578 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
3579 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3580 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3581 //\r
3582 // Append &Name1\0\r
3583 //\r
3584 UnicodeSPrint (\r
3585 StringPtr,\r
3586 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
3587 L"&%s",\r
3588 BlockData->Name\r
1436aea4 3589 );\r
82e8c138
ED
3590 } else {\r
3591 //\r
3592 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
3593 //\r
3594 UnicodeSPrint (\r
d1102dba
LG
3595 StringPtr,\r
3596 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),\r
3597 L"&OFFSET=%04X&WIDTH=%04X",\r
3598 BlockData->Offset,\r
82e8c138 3599 BlockData->Width\r
1436aea4 3600 );\r
82e8c138 3601 }\r
1436aea4 3602\r
82e8c138
ED
3603 StringPtr += StrLen (StringPtr);\r
3604 }\r
1436aea4 3605\r
82e8c138
ED
3606 //\r
3607 // Set to the got full request string.\r
3608 //\r
3609 HiiToLower (FullConfigRequest);\r
3610\r
3611 if (*ConfigRequest != NULL) {\r
3612 FreePool (*ConfigRequest);\r
3613 }\r
1436aea4 3614\r
82e8c138
ED
3615 *ConfigRequest = FullConfigRequest;\r
3616\r
3617 return TRUE;\r
3618}\r
3619\r
3620/**\r
3621 Generate ConfigRequest Header base on the varstore info.\r
3622\r
3623 @param VarStorageData The varstore info.\r
3624 @param DevicePath Device path for this varstore.\r
3625 @param ConfigHdr The config header for this varstore.\r
3626\r
3627 @retval EFI_SUCCESS Generate the header success.\r
3628 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
3629**/\r
3630EFI_STATUS\r
3631GenerateHdr (\r
1436aea4
MK
3632 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3633 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3634 OUT EFI_STRING *ConfigHdr\r
82e8c138
ED
3635 )\r
3636{\r
1436aea4
MK
3637 EFI_STRING GuidStr;\r
3638 EFI_STRING NameStr;\r
3639 EFI_STRING PathStr;\r
3640 UINTN Length;\r
3641 EFI_STATUS Status;\r
82e8c138
ED
3642\r
3643 Status = EFI_SUCCESS;\r
3644 NameStr = NULL;\r
3645 GuidStr = NULL;\r
3646 PathStr = NULL;\r
3647\r
3648 //\r
3649 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
3650 //\r
1436aea4 3651 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&VarStorageData->Guid, 1, &GuidStr);\r
82e8c138 3652 if (VarStorageData->Name != NULL) {\r
1436aea4 3653 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *)VarStorageData->Name, 2, &NameStr);\r
82e8c138
ED
3654 } else {\r
3655 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
3656 }\r
1436aea4 3657\r
82e8c138
ED
3658 GenerateSubStr (\r
3659 L"PATH=",\r
1436aea4
MK
3660 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),\r
3661 (VOID *)DevicePath,\r
82e8c138
ED
3662 1,\r
3663 &PathStr\r
3664 );\r
3665 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
3666 if (VarStorageData->Name == NULL) {\r
3667 Length += 1;\r
3668 }\r
3669\r
3670 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
3671 if (*ConfigHdr == NULL) {\r
3672 Status = EFI_OUT_OF_RESOURCES;\r
3673 goto Done;\r
3674 }\r
1436aea4 3675\r
5ad66ec6
DB
3676 StrCpyS (*ConfigHdr, Length, GuidStr);\r
3677 StrCatS (*ConfigHdr, Length, NameStr);\r
82e8c138 3678 if (VarStorageData->Name == NULL) {\r
5ad66ec6 3679 StrCatS (*ConfigHdr, Length, L"&");\r
82e8c138 3680 }\r
1436aea4 3681\r
5ad66ec6 3682 StrCatS (*ConfigHdr, Length, PathStr);\r
82e8c138
ED
3683\r
3684 //\r
3685 // Remove the last character L'&'\r
3686 //\r
3687 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
3688\r
3689Done:\r
3690 if (GuidStr != NULL) {\r
3691 FreePool (GuidStr);\r
3692 }\r
3693\r
3694 if (NameStr != NULL) {\r
3695 FreePool (NameStr);\r
3696 }\r
3697\r
3698 if (PathStr != NULL) {\r
3699 FreePool (PathStr);\r
3700 }\r
3701\r
3702 return Status;\r
3703}\r
3704\r
37cd16ac
DB
3705/**\r
3706 Update the default value in the block data which is used as bit var store.\r
3707\r
3708 For example:\r
3709 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.\r
3710 And corresponding block data info: offset==0; width==1;currently the default value\r
3711 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the\r
3712 default value of this block data shuold be:2.\r
3713\r
3714 typedef struct {\r
3715 UINT8 Bit1 : 1; //\r
3716 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.\r
3717 // (default value record for the bit field)\r
3718 ......\r
3719 }ExampleData;\r
3720\r
3721 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.\r
3722 (default value record for the Block)\r
3723\r
3724 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.\r
3725\r
3726 @param BlockLink The Link of the block data.\r
3727\r
3728**/\r
3729VOID\r
3730UpdateDefaultValue (\r
1436aea4
MK
3731 IN LIST_ENTRY *BlockLink\r
3732 )\r
37cd16ac 3733{\r
1436aea4
MK
3734 LIST_ENTRY *Link;\r
3735 LIST_ENTRY *ListEntry;\r
3736 LIST_ENTRY *LinkDefault;\r
3737 IFR_BLOCK_DATA *BlockData;\r
3738 IFR_DEFAULT_DATA *DefaultValueData;\r
3739 UINTN StartBit;\r
3740 UINTN EndBit;\r
3741 UINT32 BitFieldDefaultValue;\r
37cd16ac
DB
3742\r
3743 for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
3744 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1436aea4 3745 if (!BlockData->IsBitVar) {\r
37cd16ac
DB
3746 continue;\r
3747 }\r
1436aea4
MK
3748\r
3749 ListEntry = &BlockData->DefaultValueEntry;\r
37cd16ac
DB
3750 //\r
3751 // Update the default value in the block data with all existing default id.\r
3752 //\r
3753 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
3754 //\r
3755 // Get the default data, and the value of the default data is for some field in the block.\r
3756 // Note: Default value for bit field question is stored as UINT32.\r
3757 //\r
1436aea4 3758 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
37cd16ac
DB
3759 BitFieldDefaultValue = DefaultValueData->Value.u32;\r
3760\r
3761 StartBit = BlockData->BitOffset % 8;\r
1436aea4 3762 EndBit = StartBit + BlockData->BitWidth - 1;\r
37cd16ac
DB
3763\r
3764 //\r
3765 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.\r
3766 //\r
3767 DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);\r
3768 }\r
3769 }\r
3770}\r
3771\r
3772/**\r
3773Merge the default value in two block datas which have overlap region.\r
3774\r
3775For bit fields, their related block data may have overlap region, such as:\r
3776\r
3777typedef struct {\r
3778 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1\r
3779 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5\r
3780 // (default value record for the bit field)\r
3781 ......\r
3782}ExampleData;\r
3783\r
3784After function UpdateDefaultValue:\r
3785Block1: offset = 0; width = 1;(byte level) default = 1\r
3786Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))\r
3787(default value record for block)\r
3788\r
3789After function MergeBlockDefaultValue:\r
3790Block1: offset = 0; width = 1;(byte level) default = 65\r
3791Block2: offset = 0; width = 2;(byte level) default = 321\r
3792(Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)\r
3793\r
3794Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains\r
3795value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).\r
3796\r
3797This fuction merge the default value of these two blocks, and make the default value of block1\r
3798also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also\r
3799contain the default value of Bit1.\r
3800\r
3801We can get the total value of the whole block that just cover these two blocks(in this case is:\r
3802block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is\r
3803the first byte value of block.\r
3804\r
3805@param FirstBlock Point to the block date whose default value need to be merged.\r
3806@param SecondBlock Point to the block date whose default value need to be merged.\r
3807\r
3808**/\r
3809VOID\r
3810MergeBlockDefaultValue (\r
1436aea4
MK
3811 IN OUT IFR_BLOCK_DATA *FirstBlock,\r
3812 IN OUT IFR_BLOCK_DATA *SecondBlock\r
3813 )\r
37cd16ac 3814{\r
1436aea4
MK
3815 LIST_ENTRY *FirstListEntry;\r
3816 LIST_ENTRY *SecondListEntry;\r
3817 LIST_ENTRY *FirstDefaultLink;\r
3818 LIST_ENTRY *SecondDefaultLink;\r
3819 IFR_DEFAULT_DATA *FirstDefaultValueData;\r
3820 IFR_DEFAULT_DATA *SecondDefaultValueData;\r
3821 UINT32 *FirstDefaultValue;\r
3822 UINT32 *SecondDefaultValue;\r
3823 UINT64 TotalValue;\r
3824 UINT64 ShiftedValue;\r
3825 UINT16 OffsetShift;\r
37cd16ac
DB
3826\r
3827 FirstListEntry = &FirstBlock->DefaultValueEntry;\r
3828 for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {\r
3829 FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);\r
1436aea4 3830 SecondListEntry = &SecondBlock->DefaultValueEntry;\r
37cd16ac
DB
3831 for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {\r
3832 SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);\r
3833 if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {\r
3834 continue;\r
3835 }\r
1436aea4 3836\r
37cd16ac
DB
3837 //\r
3838 // Find default value with same default id in the two blocks.\r
3839 // Note: Default value for bit field question is stored as UINT32 type.\r
3840 //\r
1436aea4 3841 FirstDefaultValue = &FirstDefaultValueData->Value.u32;\r
37cd16ac
DB
3842 SecondDefaultValue = &SecondDefaultValueData->Value.u32;\r
3843 //\r
3844 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.\r
3845 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based\r
3846 // on the offset and width of FirstBlock and SecondBlock.\r
3847 //\r
3848 if (FirstBlock->Offset > SecondBlock->Offset) {\r
1436aea4
MK
3849 OffsetShift = FirstBlock->Offset - SecondBlock->Offset;\r
3850 ShiftedValue = LShiftU64 ((UINT64)(*FirstDefaultValue), OffsetShift * 8);\r
3851 TotalValue = ShiftedValue | (UINT64)(*SecondDefaultValue);\r
3852 *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);\r
3853 *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);\r
37cd16ac 3854 } else {\r
1436aea4
MK
3855 OffsetShift = SecondBlock->Offset -FirstBlock->Offset;\r
3856 ShiftedValue = LShiftU64 ((UINT64)(*SecondDefaultValue), OffsetShift * 8);\r
3857 TotalValue = ShiftedValue | (UINT64)(*FirstDefaultValue);\r
3858 *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);\r
3859 *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);\r
37cd16ac
DB
3860 }\r
3861 }\r
3862 }\r
3863}\r
3864\r
3865/**\r
3866\r
3867Update the default value in the block data which used as Bit VarStore\r
3868\r
3869@param BlockLink The Link of the block data.\r
3870\r
3871**/\r
3872VOID\r
3873UpdateBlockDataArray (\r
1436aea4
MK
3874 IN LIST_ENTRY *BlockLink\r
3875 )\r
37cd16ac 3876{\r
1436aea4
MK
3877 LIST_ENTRY *Link;\r
3878 LIST_ENTRY *TempLink;\r
3879 IFR_BLOCK_DATA *BlockData;\r
3880 IFR_BLOCK_DATA *NextBlockData;\r
37cd16ac
DB
3881\r
3882 //\r
3883 // 1. Update default value in BitVar block data.\r
3884 // Sine some block datas are used as BitVarStore, then the default value recored in the block\r
3885 // is for related bit field in the block. so we need to set the default value to the related bit\r
3886 // fields in the block data if the block data is used as bit varstore, then the default value of\r
3887 // the block will be updated.\r
3888 //\r
3889 UpdateDefaultValue (BlockLink);\r
3890\r
3891 //\r
3892 // 2.Update default value for overlap BitVar blcok datas.\r
3893 // For block datas have overlap region, we need to merge the default value in different blocks.\r
3894 //\r
3895 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
3896 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1436aea4 3897 if (!BlockData->IsBitVar) {\r
37cd16ac
DB
3898 continue;\r
3899 }\r
1436aea4 3900\r
37cd16ac
DB
3901 for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {\r
3902 NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);\r
1436aea4 3903 if (!NextBlockData->IsBitVar || (NextBlockData->Offset >= BlockData->Offset + BlockData->Width) || (BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width)) {\r
37cd16ac
DB
3904 continue;\r
3905 }\r
1436aea4 3906\r
37cd16ac
DB
3907 //\r
3908 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.\r
3909 //\r
3910 MergeBlockDefaultValue (BlockData, NextBlockData);\r
3911 }\r
3912 }\r
3913}\r
3914\r
82e8c138
ED
3915/**\r
3916 Generate ConfigAltResp string base on the varstore info.\r
3917\r
e68c776b 3918 @param HiiHandle Hii Handle for this hii package.\r
82e8c138
ED
3919 @param ConfigHdr The config header for this varstore.\r
3920 @param VarStorageData The varstore info.\r
3921 @param DefaultIdArray The Default id array.\r
3922 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
3923\r
3924 @retval TRUE Need to continue\r
3925 @retval Others NO need to continue or error occur.\r
3926**/\r
3927EFI_STATUS\r
3928GenerateAltConfigResp (\r
1436aea4
MK
3929 IN EFI_HII_HANDLE HiiHandle,\r
3930 IN CHAR16 *ConfigHdr,\r
3931 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3932 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
3933 IN OUT EFI_STRING *DefaultAltCfgResp\r
82e8c138
ED
3934 )\r
3935{\r
1436aea4
MK
3936 BOOLEAN DataExist;\r
3937 UINTN Length;\r
3938 LIST_ENTRY *Link;\r
3939 LIST_ENTRY *LinkData;\r
3940 LIST_ENTRY *LinkDefault;\r
3941 LIST_ENTRY *ListEntry;\r
3942 CHAR16 *StringPtr;\r
3943 IFR_BLOCK_DATA *BlockData;\r
3944 IFR_DEFAULT_DATA *DefaultId;\r
3945 IFR_DEFAULT_DATA *DefaultValueData;\r
3946 UINTN Width;\r
3947 UINT8 *TmpBuffer;\r
3948 CHAR16 *DefaultString;\r
3949 UINTN StrSize;\r
82e8c138
ED
3950\r
3951 BlockData = NULL;\r
3952 DataExist = FALSE;\r
e68c776b 3953 DefaultString = NULL;\r
82e8c138
ED
3954 //\r
3955 // Add length for <ConfigHdr> + '\0'\r
3956 //\r
3957 Length = StrLen (ConfigHdr) + 1;\r
3958\r
37cd16ac
DB
3959 UpdateBlockDataArray (&VarStorageData->BlockEntry);\r
3960\r
82e8c138
ED
3961 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
3962 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
3963 //\r
3964 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
3965 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
3966 //\r
3967 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
d1102dba 3968\r
82e8c138
ED
3969 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
3970 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1436aea4 3971 ListEntry = &BlockData->DefaultValueEntry;\r
82e8c138
ED
3972 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
3973 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
3974 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
3975 continue;\r
3976 }\r
1436aea4 3977\r
82e8c138
ED
3978 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3979 //\r
3980 // Add length for "&Name1=zzzzzzzzzzzz"\r
3981 // |1|Name|1|Value|\r
3982 //\r
3983 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
3984 } else {\r
3985 //\r
3986 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
3987 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
3988 //\r
3989 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
3990 }\r
1436aea4 3991\r
82e8c138
ED
3992 DataExist = TRUE;\r
3993 }\r
3994 }\r
3995 }\r
d1102dba 3996\r
82e8c138
ED
3997 //\r
3998 // No default value is found. The default string doesn't exist.\r
3999 //\r
4000 if (!DataExist) {\r
4001 return EFI_SUCCESS;\r
4002 }\r
4003\r
4004 //\r
4005 // Allocate buffer for the entire <DefaultAltCfgResp>\r
4006 //\r
4007 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
4008 if (*DefaultAltCfgResp == NULL) {\r
4009 return EFI_OUT_OF_RESOURCES;\r
4010 }\r
1436aea4 4011\r
82e8c138
ED
4012 StringPtr = *DefaultAltCfgResp;\r
4013\r
4014 //\r
4015 // Start with <ConfigHdr>\r
4016 //\r
5ad66ec6 4017 StrCpyS (StringPtr, Length, ConfigHdr);\r
82e8c138
ED
4018 StringPtr += StrLen (StringPtr);\r
4019\r
4020 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
4021 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
4022 //\r
4023 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
4024 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
4025 //\r
4026 UnicodeSPrint (\r
d1102dba
LG
4027 StringPtr,\r
4028 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),\r
4029 L"&%s&ALTCFG=%04X",\r
4030 ConfigHdr,\r
82e8c138
ED
4031 DefaultId->DefaultId\r
4032 );\r
4033 StringPtr += StrLen (StringPtr);\r
4034\r
4035 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
4036 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1436aea4 4037 ListEntry = &BlockData->DefaultValueEntry;\r
82e8c138
ED
4038 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
4039 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
4040 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
4041 continue;\r
4042 }\r
1436aea4 4043\r
82e8c138
ED
4044 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
4045 UnicodeSPrint (\r
d1102dba
LG
4046 StringPtr,\r
4047 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),\r
4048 L"&%s=",\r
82e8c138
ED
4049 BlockData->Name\r
4050 );\r
4051 StringPtr += StrLen (StringPtr);\r
4052 } else {\r
4053 //\r
4054 // Add <BlockConfig>\r
4055 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
4056 //\r
4057 UnicodeSPrint (\r
d1102dba 4058 StringPtr,\r
82e8c138 4059 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
d1102dba
LG
4060 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",\r
4061 BlockData->Offset,\r
82e8c138
ED
4062 BlockData->Width\r
4063 );\r
4064 StringPtr += StrLen (StringPtr);\r
4065 }\r
1436aea4 4066\r
82e8c138
ED
4067 Width = BlockData->Width;\r
4068 //\r
4069 // Convert Value to a hex string in "%x" format\r
4070 // NOTE: This is in the opposite byte that GUID and PATH use\r
4071 //\r
1436aea4
MK
4072 if (BlockData->OpCode == EFI_IFR_STRING_OP) {\r
4073 DefaultString = InternalGetString (HiiHandle, DefaultValueData->Value.string);\r
4074 TmpBuffer = AllocateZeroPool (Width);\r
bf342907
DB
4075 ASSERT (TmpBuffer != NULL);\r
4076 if (DefaultString != NULL) {\r
1436aea4 4077 StrSize = StrLen (DefaultString)* sizeof (CHAR16);\r
bf342907
DB
4078 if (StrSize > Width) {\r
4079 StrSize = Width;\r
4080 }\r
1436aea4
MK
4081\r
4082 CopyMem (TmpBuffer, (UINT8 *)DefaultString, StrSize);\r
bf342907 4083 }\r
e68c776b 4084 } else {\r
1436aea4 4085 TmpBuffer = (UINT8 *)&(DefaultValueData->Value);\r
e68c776b 4086 }\r
1436aea4
MK
4087\r
4088 for ( ; Width > 0 && (TmpBuffer != NULL); Width--) {\r
9f4048f7
HW
4089 UnicodeValueToStringS (\r
4090 StringPtr,\r
4091 Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),\r
4092 PREFIX_ZERO | RADIX_HEX,\r
4093 TmpBuffer[Width - 1],\r
4094 2\r
4095 );\r
4096 StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));\r
82e8c138 4097 }\r
1436aea4
MK
4098\r
4099 if (DefaultString != NULL) {\r
4100 FreePool (DefaultString);\r
e68c776b
DB
4101 DefaultString = NULL;\r
4102 }\r
1436aea4
MK
4103\r
4104 if ((BlockData->OpCode == EFI_IFR_STRING_OP) && (TmpBuffer != NULL)) {\r
4105 FreePool (TmpBuffer);\r
4106 TmpBuffer = NULL;\r
bf342907 4107 }\r
82e8c138
ED
4108 }\r
4109 }\r
4110 }\r
4111\r
4112 HiiToLower (*DefaultAltCfgResp);\r
4113\r
4114 return EFI_SUCCESS;\r
4115}\r
4116\r
4117/**\r
d1102dba
LG
4118 This function gets the full request string and full default value string by\r
4119 parsing IFR data in HII form packages.\r
4120\r
4121 When Request points to NULL string, the request string and default value string\r
4122 for each varstore in form package will return.\r
82e8c138
ED
4123\r
4124 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
4125 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
4126 @param Request Pointer to a null-terminated Unicode string in\r
4127 <ConfigRequest> format. When it doesn't contain\r
d1102dba 4128 any RequestElement, it will be updated to return\r
82e8c138
ED
4129 the full RequestElement retrieved from IFR data.\r
4130 If it points to NULL, the request string for the first\r
4131 varstore in form package will be merged into a\r
d1102dba 4132 <MultiConfigRequest> format string and return.\r
82e8c138
ED
4133 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
4134 <ConfigAltResp> format. When the pointer is to NULL,\r
4135 the full default value string retrieved from IFR data\r
4136 will return. When the pinter is to a string, the\r
4137 full default value string retrieved from IFR data\r
4138 will be merged into the input string and return.\r
d1102dba
LG
4139 When Request points to NULL, the default value string\r
4140 for each varstore in form package will be merged into\r
82e8c138 4141 a <MultiConfigAltResp> format string and return.\r
4a429716 4142 @param PointerProgress Optional parameter, it can be NULL.\r
d1102dba 4143 When it is not NULL, if Request is NULL, it returns NULL.\r
82e8c138
ED
4144 On return, points to a character in the Request\r
4145 string. Points to the string's null terminator if\r
4146 request was successful. Points to the most recent\r
4147 & before the first failing name / value pair (or\r
ae79d2f9
LG
4148 the beginning of the string if the failure is in\r
4149 the first name / value pair) if the request was\r
4150 not successful.\r
84f9a9ec
LG
4151 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4152 And AltCfgResp contains all default value string.\r
4153 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
d1102dba 4154 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string\r
84f9a9ec
LG
4155 can't be found in Form package.\r
4156 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 4157 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
4158\r
4159**/\r
4160EFI_STATUS\r
4161EFIAPI\r
4162GetFullStringFromHiiFormPackages (\r
1436aea4
MK
4163 IN HII_DATABASE_RECORD *DataBaseRecord,\r
4164 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4165 IN OUT EFI_STRING *Request,\r
4166 IN OUT EFI_STRING *AltCfgResp,\r
4167 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
4168 )\r
4169{\r
1436aea4
MK
4170 EFI_STATUS Status;\r
4171 UINT8 *HiiFormPackage;\r
4172 UINTN PackageSize;\r
4173 IFR_BLOCK_DATA *RequestBlockArray;\r
4174 IFR_BLOCK_DATA *BlockData;\r
4175 IFR_DEFAULT_DATA *DefaultValueData;\r
4176 IFR_DEFAULT_DATA *DefaultId;\r
4177 IFR_DEFAULT_DATA *DefaultIdArray;\r
4178 IFR_VARSTORAGE_DATA *VarStorageData;\r
4179 EFI_STRING DefaultAltCfgResp;\r
4180 EFI_STRING ConfigHdr;\r
4181 EFI_STRING StringPtr;\r
4182 EFI_STRING Progress;\r
4183\r
4184 if ((DataBaseRecord == NULL) || (DevicePath == NULL) || (Request == NULL) || (AltCfgResp == NULL)) {\r
40ae09a2 4185 return EFI_INVALID_PARAMETER;\r
ae79d2f9
LG
4186 }\r
4187\r
84f9a9ec
LG
4188 //\r
4189 // Initialize the local variables.\r
4190 //\r
4191 RequestBlockArray = NULL;\r
8567300a 4192 DefaultIdArray = NULL;\r
84f9a9ec
LG
4193 VarStorageData = NULL;\r
4194 DefaultAltCfgResp = NULL;\r
40ae09a2
ED
4195 ConfigHdr = NULL;\r
4196 HiiFormPackage = NULL;\r
4197 PackageSize = 0;\r
40ae09a2
ED
4198 Progress = *Request;\r
4199\r
4200 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
84f9a9ec 4201 if (EFI_ERROR (Status)) {\r
b572d3f0 4202 goto Done;\r
84f9a9ec
LG
4203 }\r
4204\r
4205 //\r
4a429716 4206 // 1. Get the request block array by Request String when Request string contains the block array.\r
84f9a9ec
LG
4207 //\r
4208 StringPtr = NULL;\r
4209 if (*Request != NULL) {\r
ae79d2f9
LG
4210 StringPtr = *Request;\r
4211 //\r
4212 // Jump <ConfigHdr>\r
4213 //\r
4214 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1436aea4 4215 Status = EFI_INVALID_PARAMETER;\r
ae79d2f9
LG
4216 goto Done;\r
4217 }\r
1436aea4 4218\r
ae79d2f9
LG
4219 StringPtr += StrLen (L"GUID=");\r
4220 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
4221 StringPtr++;\r
4222 }\r
1436aea4 4223\r
ae79d2f9
LG
4224 if (*StringPtr == L'\0') {\r
4225 Status = EFI_INVALID_PARAMETER;\r
4226 goto Done;\r
4227 }\r
1436aea4 4228\r
ae79d2f9 4229 StringPtr += StrLen (L"&NAME=");\r
82e8c138
ED
4230 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
4231 StringPtr++;\r
6e3f5b2a 4232 }\r
1436aea4 4233\r
82e8c138
ED
4234 if (*StringPtr == L'\0') {\r
4235 Status = EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
4236 goto Done;\r
4237 }\r
1436aea4 4238\r
82e8c138
ED
4239 StringPtr += StrLen (L"&PATH=");\r
4240 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1436aea4 4241 StringPtr++;\r
82e8c138 4242 }\r
84f9a9ec 4243\r
82e8c138 4244 if (*StringPtr == L'\0') {\r
84f9a9ec 4245 //\r
82e8c138 4246 // No request block is found.\r
84f9a9ec 4247 //\r
82e8c138 4248 StringPtr = NULL;\r
84f9a9ec 4249 }\r
84f9a9ec 4250 }\r
82e8c138 4251\r
93e3992d 4252 //\r
82e8c138 4253 // If StringPtr != NULL, get the request elements.\r
93e3992d 4254 //\r
82e8c138
ED
4255 if (StringPtr != NULL) {\r
4256 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
1436aea4 4257 RequestBlockArray = GetBlockElement (StringPtr, &Progress);\r
82e8c138 4258 } else {\r
1436aea4 4259 RequestBlockArray = GetNameElement (StringPtr, &Progress);\r
82e8c138
ED
4260 }\r
4261\r
4262 if (RequestBlockArray == NULL) {\r
4263 Status = EFI_INVALID_PARAMETER;\r
4264 goto Done;\r
84f9a9ec 4265 }\r
93e3992d 4266 }\r
82e8c138 4267\r
6e3f5b2a 4268 //\r
82e8c138 4269 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
6e3f5b2a 4270 //\r
1436aea4 4271 DefaultIdArray = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
82e8c138
ED
4272 if (DefaultIdArray == NULL) {\r
4273 Status = EFI_OUT_OF_RESOURCES;\r
6e3f5b2a
LG
4274 goto Done;\r
4275 }\r
1436aea4 4276\r
82e8c138 4277 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 4278\r
93e3992d 4279 //\r
82e8c138 4280 // Initialize VarStorageData to store the var store Block and Default value information.\r
93e3992d 4281 //\r
1436aea4 4282 VarStorageData = (IFR_VARSTORAGE_DATA *)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
82e8c138 4283 if (VarStorageData == NULL) {\r
6e3f5b2a 4284 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
4285 goto Done;\r
4286 }\r
1436aea4 4287\r
82e8c138
ED
4288 InitializeListHead (&VarStorageData->Entry);\r
4289 InitializeListHead (&VarStorageData->BlockEntry);\r
93e3992d 4290\r
84f9a9ec 4291 //\r
82e8c138 4292 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 4293 //\r
93e3992d 4294\r
82e8c138 4295 //\r
4a429716 4296 // Parse the opcode in form package to get the default setting.\r
82e8c138 4297 //\r
1436aea4
MK
4298 Status = ParseIfrData (\r
4299 DataBaseRecord->Handle,\r
4300 HiiFormPackage,\r
4301 (UINT32)PackageSize,\r
4302 *Request,\r
4303 RequestBlockArray,\r
4304 VarStorageData,\r
4305 DefaultIdArray\r
4306 );\r
82e8c138
ED
4307 if (EFI_ERROR (Status)) {\r
4308 goto Done;\r
4309 }\r
84f9a9ec 4310\r
82e8c138
ED
4311 //\r
4312 // No requested varstore in IFR data and directly return\r
4313 //\r
1436aea4 4314 if ((VarStorageData->Type == 0) && (VarStorageData->Name == NULL)) {\r
82e8c138
ED
4315 Status = EFI_SUCCESS;\r
4316 goto Done;\r
4317 }\r
4318\r
4319 //\r
4320 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
4321 //\r
4322 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
4323 if (EFI_ERROR (Status)) {\r
4324 goto Done;\r
4325 }\r
4326\r
4327 if (RequestBlockArray == NULL) {\r
1436aea4 4328 if (!GenerateConfigRequest (ConfigHdr, VarStorageData, &Status, Request)) {\r
82e8c138 4329 goto Done;\r
84f9a9ec 4330 }\r
93e3992d 4331 }\r
82e8c138
ED
4332\r
4333 //\r
4334 // 4. Construct Default Value string in AltResp according to request element.\r
4335 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
4336 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
4337 //\r
1436aea4 4338 Status = GenerateAltConfigResp (DataBaseRecord->Handle, ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
82e8c138
ED
4339 if (EFI_ERROR (Status)) {\r
4340 goto Done;\r
4341 }\r
93e3992d 4342\r
84f9a9ec 4343 //\r
4a429716 4344 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.\r
84f9a9ec 4345 //\r
1436aea4 4346 if ((*AltCfgResp != NULL) && (DefaultAltCfgResp != NULL)) {\r
84f9a9ec
LG
4347 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
4348 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
4349 } else if (*AltCfgResp == NULL) {\r
4350 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 4351 }\r
93e3992d 4352\r
84f9a9ec
LG
4353Done:\r
4354 if (RequestBlockArray != NULL) {\r
4355 //\r
4356 // Free Link Array RequestBlockArray\r
4357 //\r
4358 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
4359 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
4360 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
4361 if (BlockData->Name != NULL) {\r
4362 FreePool (BlockData->Name);\r
4363 }\r
1436aea4 4364\r
84f9a9ec
LG
4365 FreePool (BlockData);\r
4366 }\r
4367\r
4368 FreePool (RequestBlockArray);\r
93e3992d 4369 }\r
82e8c138 4370\r
84f9a9ec
LG
4371 if (VarStorageData != NULL) {\r
4372 //\r
4373 // Free link array VarStorageData\r
4374 //\r
4375 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
4376 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
4377 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
4378 if (BlockData->Name != NULL) {\r
4379 FreePool (BlockData->Name);\r
4380 }\r
1436aea4 4381\r
84f9a9ec
LG
4382 //\r
4383 // Free default value link array\r
4384 //\r
4385 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
4386 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
4387 RemoveEntryList (&DefaultValueData->Entry);\r
4388 FreePool (DefaultValueData);\r
4389 }\r
1436aea4 4390\r
84f9a9ec 4391 FreePool (BlockData);\r
63d55bb9 4392 }\r
1436aea4
MK
4393\r
4394 if (VarStorageData->Name != NULL) {\r
4395 FreePool (VarStorageData->Name);\r
4396 VarStorageData->Name = NULL;\r
a0b0cd73 4397 }\r
1436aea4 4398\r
84f9a9ec 4399 FreePool (VarStorageData);\r
93e3992d 4400 }\r
4401\r
84f9a9ec
LG
4402 if (DefaultIdArray != NULL) {\r
4403 //\r
4404 // Free DefaultId Array\r
4405 //\r
4406 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
4407 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
4408 RemoveEntryList (&DefaultId->Entry);\r
4409 FreePool (DefaultId);\r
4410 }\r
1436aea4 4411\r
84f9a9ec
LG
4412 FreePool (DefaultIdArray);\r
4413 }\r
82e8c138 4414\r
84f9a9ec 4415 //\r
d1102dba 4416 // Free the allocated string\r
84f9a9ec 4417 //\r
84f9a9ec
LG
4418 if (ConfigHdr != NULL) {\r
4419 FreePool (ConfigHdr);\r
4420 }\r
93e3992d 4421\r
84f9a9ec 4422 //\r
4a429716 4423 // Free Package data\r
84f9a9ec 4424 //\r
8567300a
LG
4425 if (HiiFormPackage != NULL) {\r
4426 FreePool (HiiFormPackage);\r
676df92c 4427 }\r
63d55bb9 4428\r
ae79d2f9
LG
4429 if (PointerProgress != NULL) {\r
4430 if (*Request == NULL) {\r
4431 *PointerProgress = NULL;\r
4432 } else if (EFI_ERROR (Status)) {\r
82e8c138 4433 *PointerProgress = *Request;\r
ae79d2f9
LG
4434 } else {\r
4435 *PointerProgress = *Request + StrLen (*Request);\r
4436 }\r
4437 }\r
4438\r
93e3992d 4439 return Status;\r
4440}\r
4441\r
cce6230f 4442/**\r
d1102dba 4443 This function gets the full request resp string by\r
cce6230f
ED
4444 parsing IFR data in HII form packages.\r
4445\r
4446 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4447 instance.\r
d1102dba
LG
4448 @param EfiVarStoreInfo The efi varstore info which is save in the EFI\r
4449 varstore data structure.\r
cce6230f
ED
4450 @param Request Pointer to a null-terminated Unicode string in\r
4451 <ConfigRequest> format.\r
4452 @param RequestResp Pointer to a null-terminated Unicode string in\r
4453 <ConfigResp> format.\r
4454 @param AccessProgress On return, points to a character in the Request\r
4455 string. Points to the string's null terminator if\r
4456 request was successful. Points to the most recent\r
4457 & before the first failing name / value pair (or\r
4458 the beginning of the string if the failure is in\r
4459 the first name / value pair) if the request was\r
4460 not successful.\r
4461\r
4462 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4463 And AltCfgResp contains all default value string.\r
4464 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
4465 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
4466\r
4467**/\r
4468EFI_STATUS\r
4469GetConfigRespFromEfiVarStore (\r
4470 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
d1102dba 4471 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,\r
cce6230f
ED
4472 IN EFI_STRING Request,\r
4473 OUT EFI_STRING *RequestResp,\r
4474 OUT EFI_STRING *AccessProgress\r
4475 )\r
4476{\r
1436aea4
MK
4477 EFI_STATUS Status;\r
4478 EFI_STRING VarStoreName;\r
4479 UINTN NameSize;\r
4480 UINT8 *VarStore;\r
4481 UINTN BufferSize;\r
cce6230f 4482\r
7248790e
ED
4483 Status = EFI_SUCCESS;\r
4484 BufferSize = 0;\r
4485 VarStore = NULL;\r
4486 VarStoreName = NULL;\r
4487 *AccessProgress = Request;\r
b68ccac1 4488\r
1436aea4 4489 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
b68ccac1 4490 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
cce6230f
ED
4491 if (VarStoreName == NULL) {\r
4492 Status = EFI_OUT_OF_RESOURCES;\r
4493 goto Done;\r
4494 }\r
d1102dba 4495\r
1436aea4 4496 AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
d1102dba 4497\r
cce6230f
ED
4498 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
4499 if (Status != EFI_BUFFER_TOO_SMALL) {\r
4500 goto Done;\r
4501 }\r
4502\r
4503 VarStore = AllocateZeroPool (BufferSize);\r
4504 ASSERT (VarStore != NULL);\r
4505 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
4506 if (EFI_ERROR (Status)) {\r
4507 goto Done;\r
4508 }\r
4509\r
1436aea4 4510 Status = HiiBlockToConfig (This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
cce6230f
ED
4511 if (EFI_ERROR (Status)) {\r
4512 goto Done;\r
4513 }\r
4514\r
4515Done:\r
4516 if (VarStoreName != NULL) {\r
4517 FreePool (VarStoreName);\r
4518 }\r
4519\r
4520 if (VarStore != NULL) {\r
4521 FreePool (VarStore);\r
4522 }\r
4523\r
4524 return Status;\r
4525}\r
4526\r
cce6230f 4527/**\r
d1102dba 4528 This function route the full request resp string for efi varstore.\r
cce6230f
ED
4529\r
4530 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4531 instance.\r
d1102dba
LG
4532 @param EfiVarStoreInfo The efi varstore info which is save in the EFI\r
4533 varstore data structure.\r
cce6230f
ED
4534 @param RequestResp Pointer to a null-terminated Unicode string in\r
4535 <ConfigResp> format.\r
4536 @param Result Pointer to a null-terminated Unicode string in\r
4537 <ConfigResp> format.\r
d1102dba 4538\r
cce6230f
ED
4539 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4540 And AltCfgResp contains all default value string.\r
4541 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
4542 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
4543\r
4544**/\r
4545EFI_STATUS\r
4546RouteConfigRespForEfiVarStore (\r
4547 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
d1102dba 4548 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,\r
cce6230f
ED
4549 IN EFI_STRING RequestResp,\r
4550 OUT EFI_STRING *Result\r
4551 )\r
4552{\r
1436aea4
MK
4553 EFI_STATUS Status;\r
4554 EFI_STRING VarStoreName;\r
4555 UINTN NameSize;\r
4556 UINT8 *VarStore;\r
4557 UINTN BufferSize;\r
4558 UINTN BlockSize;\r
cce6230f
ED
4559\r
4560 Status = EFI_SUCCESS;\r
4561 BufferSize = 0;\r
4562 VarStore = NULL;\r
4563 VarStoreName = NULL;\r
1436aea4 4564 *Result = RequestResp;\r
cce6230f 4565\r
1436aea4 4566 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
b68ccac1 4567 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
cce6230f
ED
4568 if (VarStoreName == NULL) {\r
4569 Status = EFI_OUT_OF_RESOURCES;\r
4570 goto Done;\r
4571 }\r
1436aea4
MK
4572\r
4573 AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
d1102dba 4574\r
cce6230f
ED
4575 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
4576 if (Status != EFI_BUFFER_TOO_SMALL) {\r
237e849d 4577 DEBUG ((DEBUG_ERROR, "The variable does not exist!"));\r
cce6230f
ED
4578 goto Done;\r
4579 }\r
4580\r
4581 BlockSize = BufferSize;\r
1436aea4 4582 VarStore = AllocateZeroPool (BufferSize);\r
cce6230f
ED
4583 ASSERT (VarStore != NULL);\r
4584 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
4585 if (EFI_ERROR (Status)) {\r
4586 goto Done;\r
4587 }\r
4588\r
1436aea4 4589 Status = HiiConfigToBlock (This, RequestResp, VarStore, &BlockSize, Result);\r
cce6230f
ED
4590 if (EFI_ERROR (Status)) {\r
4591 goto Done;\r
4592 }\r
4593\r
4594 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
4595 if (EFI_ERROR (Status)) {\r
237e849d 4596 *Result = RequestResp;\r
cce6230f
ED
4597 goto Done;\r
4598 }\r
4599\r
4600Done:\r
4601 if (VarStoreName != NULL) {\r
4602 FreePool (VarStoreName);\r
4603 }\r
4604\r
4605 if (VarStore != NULL) {\r
4606 FreePool (VarStore);\r
4607 }\r
4608\r
4609 return Status;\r
4610}\r
4611\r
82e8c138
ED
4612/**\r
4613 Validate the config request elements.\r
4614\r
d1102dba 4615 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,\r
82e8c138
ED
4616 without configHdr field.\r
4617\r
4618 @retval CHAR16 * THE first Name/value pair not correct.\r
4619 @retval NULL Success parse the name/value pair\r
4620**/\r
4621CHAR16 *\r
4622OffsetWidthValidate (\r
1436aea4 4623 CHAR16 *ConfigElements\r
82e8c138
ED
4624 )\r
4625{\r
1436aea4
MK
4626 CHAR16 *StringPtr;\r
4627 CHAR16 *RetVal;\r
82e8c138
ED
4628\r
4629 StringPtr = ConfigElements;\r
4630\r
4631 while (1) {\r
1436aea4 4632 RetVal = StringPtr;\r
82e8c138
ED
4633 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
4634 return RetVal;\r
4635 }\r
4636\r
4637 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4638 StringPtr++;\r
4639 }\r
1436aea4 4640\r
82e8c138
ED
4641 if (*StringPtr == L'\0') {\r
4642 return RetVal;\r
4643 }\r
4644\r
4645 StringPtr += StrLen (L"&WIDTH=");\r
4646 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
1436aea4 4647 StringPtr++;\r
82e8c138
ED
4648 }\r
4649\r
4650 if (*StringPtr == L'\0') {\r
4651 return NULL;\r
4652 }\r
4653 }\r
4654}\r
4655\r
4656/**\r
4657 Validate the config request elements.\r
4658\r
d1102dba 4659 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,\r
82e8c138
ED
4660 without configHdr field.\r
4661\r
4662 @retval CHAR16 * THE first Name/value pair not correct.\r
4663 @retval NULL Success parse the name/value pair\r
4664\r
4665**/\r
4666CHAR16 *\r
4667NameValueValidate (\r
1436aea4 4668 CHAR16 *ConfigElements\r
82e8c138
ED
4669 )\r
4670{\r
1436aea4
MK
4671 CHAR16 *StringPtr;\r
4672 CHAR16 *RetVal;\r
82e8c138
ED
4673\r
4674 StringPtr = ConfigElements;\r
4675\r
4676 while (1) {\r
4677 RetVal = StringPtr;\r
4678 if (*StringPtr != L'&') {\r
4679 return RetVal;\r
4680 }\r
1436aea4 4681\r
82e8c138
ED
4682 StringPtr += 1;\r
4683\r
4684 StringPtr = StrStr (StringPtr, L"&");\r
d1102dba 4685\r
82e8c138
ED
4686 if (StringPtr == NULL) {\r
4687 return NULL;\r
4688 }\r
4689 }\r
4690}\r
4691\r
4692/**\r
4693 Validate the config request string.\r
4694\r
4695 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
4696\r
4697 @retval CHAR16 * THE first element not correct.\r
4698 @retval NULL Success parse the name/value pair\r
4699\r
4700**/\r
4701CHAR16 *\r
4702ConfigRequestValidate (\r
1436aea4 4703 CHAR16 *ConfigRequest\r
82e8c138
ED
4704 )\r
4705{\r
1436aea4
MK
4706 BOOLEAN HasNameField;\r
4707 CHAR16 *StringPtr;\r
82e8c138
ED
4708\r
4709 HasNameField = TRUE;\r
4710 StringPtr = ConfigRequest;\r
4711\r
4712 //\r
4713 // Check <ConfigHdr>\r
4714 //\r
4715 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4716 return ConfigRequest;\r
4717 }\r
1436aea4 4718\r
82e8c138
ED
4719 StringPtr += StrLen (L"GUID=");\r
4720 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
4721 StringPtr++;\r
4722 }\r
1436aea4 4723\r
82e8c138
ED
4724 if (*StringPtr == L'\0') {\r
4725 return ConfigRequest;\r
4726 }\r
1436aea4 4727\r
82e8c138
ED
4728 StringPtr += StrLen (L"&NAME=");\r
4729 if (*StringPtr == L'&') {\r
4730 HasNameField = FALSE;\r
4731 }\r
1436aea4 4732\r
82e8c138
ED
4733 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
4734 StringPtr++;\r
4735 }\r
1436aea4 4736\r
82e8c138
ED
4737 if (*StringPtr == L'\0') {\r
4738 return ConfigRequest;\r
4739 }\r
1436aea4 4740\r
82e8c138
ED
4741 StringPtr += StrLen (L"&PATH=");\r
4742 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1436aea4 4743 StringPtr++;\r
82e8c138
ED
4744 }\r
4745\r
4746 if (*StringPtr == L'\0') {\r
4747 return NULL;\r
4748 }\r
4749\r
4750 if (HasNameField) {\r
4751 //\r
4752 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
4753 //\r
1436aea4 4754 return OffsetWidthValidate (StringPtr);\r
82e8c138
ED
4755 } else {\r
4756 //\r
4757 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
4758 //\r
1436aea4 4759 return NameValueValidate (StringPtr);\r
82e8c138
ED
4760 }\r
4761}\r
4762\r
93e3992d 4763/**\r
4764 This function allows a caller to extract the current configuration\r
4765 for one or more named elements from one or more drivers.\r
4766\r
4767 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4768 instance.\r
4769 @param Request A null-terminated Unicode string in\r
4770 <MultiConfigRequest> format.\r
4771 @param Progress On return, points to a character in the Request\r
4772 string. Points to the string's null terminator if\r
4773 request was successful. Points to the most recent\r
4774 & before the first failing name / value pair (or\r
4775 the beginning of the string if the failure is in\r
4776 the first name / value pair) if the request was\r
4777 not successful.\r
4778 @param Results Null-terminated Unicode string in\r
4779 <MultiConfigAltResp> format which has all values\r
4780 filled in for the names in the Request string.\r
4781 String to be allocated by the called function.\r
4782\r
4783 @retval EFI_SUCCESS The Results string is filled with the values\r
4784 corresponding to all requested names.\r
4785 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
4786 results that must be stored awaiting possible\r
4787 future protocols.\r
4788 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
4789 Progress set to the "G" in "GUID" of the routing\r
4790 header that doesn't match. Note: There is no\r
4791 requirement that all routing data be validated\r
4792 before any configuration extraction.\r
4793 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
4794 parameter would result in this type of error. The\r
4795 Progress parameter is set to NULL.\r
4796 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
4797 before the error or the beginning of the string.\r
46c3efbb 4798 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII\r
d1102dba 4799 Configuration Access Protocol returned\r
46c3efbb
ED
4800 EFI_INVALID_PARAMETER. Progress set to most recent\r
4801 & before the error or the beginning of the string.\r
93e3992d 4802\r
4803**/\r
4804EFI_STATUS\r
4805EFIAPI\r
4806HiiConfigRoutingExtractConfig (\r
4807 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4808 IN CONST EFI_STRING Request,\r
4809 OUT EFI_STRING *Progress,\r
4810 OUT EFI_STRING *Results\r
4811 )\r
4812{\r
1436aea4
MK
4813 HII_DATABASE_PRIVATE_DATA *Private;\r
4814 EFI_STRING StringPtr;\r
4815 EFI_STRING ConfigRequest;\r
4816 UINTN Length;\r
4817 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
4818 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
4819 EFI_STATUS Status;\r
4820 LIST_ENTRY *Link;\r
4821 HII_DATABASE_RECORD *Database;\r
4822 UINT8 *DevicePathPkg;\r
4823 UINT8 *CurrentDevicePath;\r
4824 EFI_HANDLE DriverHandle;\r
4825 EFI_HII_HANDLE HiiHandle;\r
4826 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4827 EFI_STRING AccessProgress;\r
4828 EFI_STRING AccessResults;\r
4829 EFI_STRING AccessProgressBackup;\r
4830 EFI_STRING AccessResultsBackup;\r
4831 EFI_STRING DefaultResults;\r
4832 BOOLEAN FirstElement;\r
4833 BOOLEAN IfrDataParsedFlag;\r
4834 BOOLEAN IsEfiVarStore;\r
4835 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4836 EFI_STRING ErrorPtr;\r
4837 UINTN DevicePathSize;\r
4838 UINTN ConigStringSize;\r
4839 UINTN ConigStringSizeNewsize;\r
4840 EFI_STRING ConfigStringPtr;\r
4841\r
4842 if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {\r
93e3992d 4843 return EFI_INVALID_PARAMETER;\r
4844 }\r
4845\r
4846 if (Request == NULL) {\r
4847 *Progress = NULL;\r
4848 return EFI_INVALID_PARAMETER;\r
4849 }\r
4850\r
1436aea4
MK
4851 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4852 StringPtr = Request;\r
4853 *Progress = StringPtr;\r
4854 DefaultResults = NULL;\r
4855 ConfigRequest = NULL;\r
4856 Status = EFI_SUCCESS;\r
4857 AccessResults = NULL;\r
4858 AccessProgress = NULL;\r
74e8963c
DB
4859 AccessResultsBackup = NULL;\r
4860 AccessProgressBackup = NULL;\r
1436aea4
MK
4861 DevicePath = NULL;\r
4862 IfrDataParsedFlag = FALSE;\r
4863 IsEfiVarStore = FALSE;\r
4864 EfiVarStoreInfo = NULL;\r
93e3992d 4865\r
4866 //\r
4867 // The first element of <MultiConfigRequest> should be\r
4868 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4869 //\r
4870 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4871 return EFI_INVALID_PARAMETER;\r
4872 }\r
4873\r
8d00a0f1 4874 FirstElement = TRUE;\r
4875\r
93e3992d 4876 //\r
4877 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4878 // Results if this fix length is insufficient.\r
4879 //\r
1436aea4 4880 *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
93e3992d 4881 if (*Results == NULL) {\r
4882 return EFI_OUT_OF_RESOURCES;\r
4883 }\r
4884\r
4885 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4886 //\r
4887 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
4888 // or most recent & before the error.\r
4889 //\r
4890 if (StringPtr == Request) {\r
4891 *Progress = StringPtr;\r
4892 } else {\r
4893 *Progress = StringPtr - 1;\r
4894 }\r
4895\r
4896 //\r
4897 // Process each <ConfigRequest> of <MultiConfigRequest>\r
4898 //\r
1436aea4 4899 Length = CalculateConfigStringLen (StringPtr);\r
93e3992d 4900 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4901 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
4902 Status = EFI_OUT_OF_RESOURCES;\r
4903 goto Done;\r
93e3992d 4904 }\r
1436aea4 4905\r
93e3992d 4906 *(ConfigRequest + Length) = 0;\r
4907\r
4908 //\r
4909 // Get the UEFI device path\r
4910 //\r
1436aea4 4911 Status = GetDevicePath (ConfigRequest, (UINT8 **)&DevicePath);\r
93e3992d 4912 if (EFI_ERROR (Status)) {\r
84f9a9ec 4913 goto Done;\r
93e3992d 4914 }\r
4915\r
4916 //\r
84f9a9ec
LG
4917 // Find driver which matches the routing data.\r
4918 //\r
1436aea4
MK
4919 DriverHandle = NULL;\r
4920 HiiHandle = NULL;\r
4921 Database = NULL;\r
84f9a9ec
LG
4922 for (Link = Private->DatabaseList.ForwardLink;\r
4923 Link != &Private->DatabaseList;\r
4924 Link = Link->ForwardLink\r
1436aea4
MK
4925 )\r
4926 {\r
84f9a9ec 4927 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
4928 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4929 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4
MK
4930 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);\r
4931 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigRequest)) {\r
84f9a9ec
LG
4932 DriverHandle = Database->DriverHandle;\r
4933 HiiHandle = Database->Handle;\r
4934 break;\r
4935 }\r
4936 }\r
4937 }\r
d1102dba 4938\r
84f9a9ec
LG
4939 //\r
4940 // Try to find driver handle by device path.\r
93e3992d 4941 //\r
84f9a9ec
LG
4942 if (DriverHandle == NULL) {\r
4943 TempDevicePath = DevicePath;\r
1436aea4
MK
4944 Status = gBS->LocateDevicePath (\r
4945 &gEfiDevicePathProtocolGuid,\r
4946 &TempDevicePath,\r
4947 &DriverHandle\r
4948 );\r
84f9a9ec
LG
4949 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4950 //\r
4951 // Routing data does not match any known driver.\r
4952 // Set Progress to the 'G' in "GUID" of the routing header.\r
4953 //\r
4954 *Progress = StringPtr;\r
1436aea4 4955 Status = EFI_NOT_FOUND;\r
84f9a9ec
LG
4956 goto Done;\r
4957 }\r
4958 }\r
82e8c138
ED
4959\r
4960 //\r
4961 // Validate ConfigRequest String.\r
4962 //\r
1436aea4 4963 ErrorPtr = ConfigRequestValidate (ConfigRequest);\r
82e8c138
ED
4964 if (ErrorPtr != NULL) {\r
4965 *Progress = StrStr (StringPtr, ErrorPtr);\r
1436aea4 4966 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
4967 goto Done;\r
4968 }\r
4969\r
84f9a9ec 4970 //\r
82e8c138 4971 // Check whether ConfigRequest contains request string.\r
84f9a9ec 4972 //\r
6e3f5b2a 4973 IfrDataParsedFlag = FALSE;\r
1436aea4 4974 if ((HiiHandle != NULL) && !GetElementsFromRequest (ConfigRequest)) {\r
93e3992d 4975 //\r
d1102dba 4976 // Get the full request string from IFR when HiiPackage is registered to HiiHandle\r
93e3992d 4977 //\r
6e3f5b2a 4978 IfrDataParsedFlag = TRUE;\r
1436aea4 4979 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 4980 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
4981 //\r
4982 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
4983 // Map it to the progress on <MultiConfigRequest> then return it.\r
4984 //\r
82e8c138 4985 ASSERT (AccessProgress != NULL);\r
ae79d2f9 4986 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
4987 goto Done;\r
4988 }\r
1436aea4 4989\r
1f1cb2f2
LG
4990 //\r
4991 // Not any request block is found.\r
4992 //\r
1436aea4 4993 if (!GetElementsFromRequest (ConfigRequest)) {\r
76c24251 4994 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
4995 goto NextConfigString;\r
4996 }\r
93e3992d 4997 }\r
4998\r
4999 //\r
cce6230f 5000 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 5001 //\r
1436aea4 5002 Status = GetVarStoreType (Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
cce6230f
ED
5003 if (EFI_ERROR (Status)) {\r
5004 goto Done;\r
5005 }\r
d1102dba 5006\r
cce6230f
ED
5007 if (IsEfiVarStore) {\r
5008 //\r
5009 // Call the GetVariable function to extract settings.\r
5010 //\r
1436aea4 5011 Status = GetConfigRespFromEfiVarStore (This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
82e8c138 5012 FreePool (EfiVarStoreInfo);\r
74e8963c
DB
5013 if (EFI_ERROR (Status)) {\r
5014 //\r
5015 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
5016 // Map it to the progress on <MultiConfigRequest> then return it.\r
5017 //\r
5018 *Progress = StrStr (StringPtr, AccessProgress);\r
5019 goto Done;\r
5020 }\r
5021\r
5022 //\r
5023 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.\r
5024 //\r
5025 Status = gBS->HandleProtocol (\r
5026 DriverHandle,\r
5027 &gEfiHiiConfigAccessProtocolGuid,\r
1436aea4 5028 (VOID **)&ConfigAccess\r
74e8963c
DB
5029 );\r
5030 if (EFI_ERROR (Status)) {\r
5031 //\r
5032 // The driver has EfiVarStore, may not install ConfigAccess protocol.\r
5033 // So ignore the error status in this case.\r
5034 //\r
5035 Status = EFI_SUCCESS;\r
5036 } else {\r
5037 Status = ConfigAccess->ExtractConfig (\r
5038 ConfigAccess,\r
5039 ConfigRequest,\r
5040 &AccessProgressBackup,\r
5041 &AccessResultsBackup\r
5042 );\r
1436aea4 5043 if (!EFI_ERROR (Status)) {\r
74e8963c 5044 //\r
1436aea4 5045 // Merge the AltCfgResp in AccessResultsBackup to AccessResults\r
74e8963c
DB
5046 //\r
5047 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {\r
1436aea4
MK
5048 ConigStringSize = StrSize (AccessResults);\r
5049 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");\r
74e8963c 5050 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);\r
1436aea4
MK
5051 AccessResults = (EFI_STRING)ReallocatePool (\r
5052 ConigStringSize,\r
5053 ConigStringSizeNewsize,\r
5054 AccessResults\r
5055 );\r
74e8963c
DB
5056 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);\r
5057 }\r
5058 } else {\r
5059 //\r
5060 // In the ExtractConfig function of some driver may not support EfiVarStore,\r
5061 // may return error status, just ignore the error status in this case.\r
5062 //\r
5063 Status = EFI_SUCCESS;\r
5064 }\r
1436aea4 5065\r
74e8963c
DB
5066 if (AccessResultsBackup != NULL) {\r
5067 FreePool (AccessResultsBackup);\r
5068 AccessResultsBackup = NULL;\r
5069 }\r
5070 }\r
cce6230f
ED
5071 } else {\r
5072 //\r
5073 // Call corresponding ConfigAccess protocol to extract settings\r
5074 //\r
5075 Status = gBS->HandleProtocol (\r
5076 DriverHandle,\r
5077 &gEfiHiiConfigAccessProtocolGuid,\r
1436aea4 5078 (VOID **)&ConfigAccess\r
cce6230f 5079 );\r
a115a9ef
EC
5080 if (EFI_ERROR (Status)) {\r
5081 goto Done;\r
5082 }\r
93e3992d 5083\r
cce6230f
ED
5084 Status = ConfigAccess->ExtractConfig (\r
5085 ConfigAccess,\r
5086 ConfigRequest,\r
5087 &AccessProgress,\r
5088 &AccessResults\r
5089 );\r
5090 }\r
1436aea4 5091\r
93e3992d 5092 if (EFI_ERROR (Status)) {\r
5093 //\r
5094 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
5095 // Map it to the progress on <MultiConfigRequest> then return it.\r
5096 //\r
8d00a0f1 5097 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 5098 goto Done;\r
93e3992d 5099 }\r
5100\r
5101 //\r
8d00a0f1 5102 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4a429716 5103 // which separates the first <ConfigAltResp> and the following ones.\r
93e3992d 5104 //\r
5105 ASSERT (*AccessProgress == 0);\r
8d00a0f1 5106\r
84f9a9ec 5107 //\r
d1102dba 5108 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
84f9a9ec 5109 //\r
1436aea4 5110 if (!IfrDataParsedFlag && (HiiHandle != NULL)) {\r
ae79d2f9
LG
5111 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
5112 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 5113 }\r
ae79d2f9 5114\r
84f9a9ec
LG
5115 FreePool (DevicePath);\r
5116 DevicePath = NULL;\r
84f9a9ec 5117\r
ae79d2f9
LG
5118 if (DefaultResults != NULL) {\r
5119 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
5120 ASSERT_EFI_ERROR (Status);\r
5121 FreePool (DefaultResults);\r
5122 DefaultResults = NULL;\r
5123 }\r
d1102dba 5124\r
82e8c138 5125NextConfigString:\r
8d00a0f1 5126 if (!FirstElement) {\r
5127 Status = AppendToMultiString (Results, L"&");\r
5128 ASSERT_EFI_ERROR (Status);\r
5129 }\r
d1102dba 5130\r
93e3992d 5131 Status = AppendToMultiString (Results, AccessResults);\r
5132 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 5133\r
5134 FirstElement = FALSE;\r
84f9a9ec 5135\r
676df92c 5136 FreePool (AccessResults);\r
93e3992d 5137 AccessResults = NULL;\r
676df92c 5138 FreePool (ConfigRequest);\r
93e3992d 5139 ConfigRequest = NULL;\r
5140\r
5141 //\r
5142 // Go to next <ConfigRequest> (skip '&').\r
5143 //\r
5144 StringPtr += Length;\r
5145 if (*StringPtr == 0) {\r
5146 *Progress = StringPtr;\r
5147 break;\r
5148 }\r
5149\r
5150 StringPtr++;\r
93e3992d 5151 }\r
5152\r
84f9a9ec
LG
5153Done:\r
5154 if (EFI_ERROR (Status)) {\r
5155 FreePool (*Results);\r
6e3f5b2a 5156 *Results = NULL;\r
84f9a9ec 5157 }\r
d1102dba 5158\r
84f9a9ec
LG
5159 if (ConfigRequest != NULL) {\r
5160 FreePool (ConfigRequest);\r
5161 }\r
d1102dba 5162\r
84f9a9ec
LG
5163 if (AccessResults != NULL) {\r
5164 FreePool (AccessResults);\r
5165 }\r
d1102dba 5166\r
84f9a9ec
LG
5167 if (DefaultResults != NULL) {\r
5168 FreePool (DefaultResults);\r
5169 }\r
d1102dba 5170\r
84f9a9ec
LG
5171 if (DevicePath != NULL) {\r
5172 FreePool (DevicePath);\r
d1102dba 5173 }\r
93e3992d 5174\r
84f9a9ec 5175 return Status;\r
93e3992d 5176}\r
5177\r
93e3992d 5178/**\r
5179 This function allows the caller to request the current configuration for the\r
5180 entirety of the current HII database and returns the data in a\r
5181 null-terminated Unicode string.\r
5182\r
5183 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5184 instance.\r
5185 @param Results Null-terminated Unicode string in\r
5186 <MultiConfigAltResp> format which has all values\r
d1102dba
LG
5187 filled in for the entirety of the current HII\r
5188 database. String to be allocated by the called\r
c0a3c3da 5189 function. De-allocation is up to the caller.\r
93e3992d 5190\r
5191 @retval EFI_SUCCESS The Results string is filled with the values\r
5192 corresponding to all requested names.\r
5193 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
5194 results that must be stored awaiting possible\r
5195 future protocols.\r
5196 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
5197 parameter would result in this type of error.\r
5198\r
5199**/\r
5200EFI_STATUS\r
5201EFIAPI\r
5202HiiConfigRoutingExportConfig (\r
5203 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5204 OUT EFI_STRING *Results\r
5205 )\r
5206{\r
1436aea4
MK
5207 EFI_STATUS Status;\r
5208 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5209 EFI_STRING AccessResults;\r
5210 EFI_STRING Progress;\r
5211 EFI_STRING StringPtr;\r
5212 EFI_STRING ConfigRequest;\r
5213 UINTN Index;\r
5214 EFI_HANDLE *ConfigAccessHandles;\r
5215 UINTN NumberConfigAccessHandles;\r
5216 BOOLEAN FirstElement;\r
5217 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
5218 EFI_HII_HANDLE HiiHandle;\r
5219 EFI_STRING DefaultResults;\r
5220 HII_DATABASE_PRIVATE_DATA *Private;\r
5221 LIST_ENTRY *Link;\r
5222 HII_DATABASE_RECORD *Database;\r
5223 UINT8 *DevicePathPkg;\r
5224 UINT8 *CurrentDevicePath;\r
5225 BOOLEAN IfrDataParsedFlag;\r
5226\r
5227 if ((This == NULL) || (Results == NULL)) {\r
93e3992d 5228 return EFI_INVALID_PARAMETER;\r
5229 }\r
5230\r
84f9a9ec
LG
5231 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5232\r
93e3992d 5233 //\r
5234 // Allocate a fix length of memory to store Results. Reallocate memory for\r
5235 // Results if this fix length is insufficient.\r
5236 //\r
1436aea4 5237 *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
93e3992d 5238 if (*Results == NULL) {\r
5239 return EFI_OUT_OF_RESOURCES;\r
5240 }\r
5241\r
8d00a0f1 5242 NumberConfigAccessHandles = 0;\r
1436aea4
MK
5243 Status = gBS->LocateHandleBuffer (\r
5244 ByProtocol,\r
5245 &gEfiHiiConfigAccessProtocolGuid,\r
5246 NULL,\r
5247 &NumberConfigAccessHandles,\r
5248 &ConfigAccessHandles\r
5249 );\r
8d00a0f1 5250 if (EFI_ERROR (Status)) {\r
5251 return Status;\r
5252 }\r
93e3992d 5253\r
8d00a0f1 5254 FirstElement = TRUE;\r
93e3992d 5255\r
8d00a0f1 5256 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 5257 Status = gBS->HandleProtocol (\r
8d00a0f1 5258 ConfigAccessHandles[Index],\r
93e3992d 5259 &gEfiHiiConfigAccessProtocolGuid,\r
1436aea4 5260 (VOID **)&ConfigAccess\r
93e3992d 5261 );\r
8d00a0f1 5262 if (EFI_ERROR (Status)) {\r
5263 continue;\r
5264 }\r
93e3992d 5265\r
84f9a9ec
LG
5266 //\r
5267 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
5268 //\r
ae79d2f9 5269 IfrDataParsedFlag = FALSE;\r
1436aea4
MK
5270 Progress = NULL;\r
5271 HiiHandle = NULL;\r
5272 DefaultResults = NULL;\r
5273 Database = NULL;\r
5274 ConfigRequest = NULL;\r
5275 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
5276 if (DevicePath != NULL) {\r
5277 for (Link = Private->DatabaseList.ForwardLink;\r
5278 Link != &Private->DatabaseList;\r
5279 Link = Link->ForwardLink\r
1436aea4
MK
5280 )\r
5281 {\r
84f9a9ec
LG
5282 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
5283 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
5284 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 5285 if (CompareMem (\r
84f9a9ec
LG
5286 DevicePath,\r
5287 CurrentDevicePath,\r
1436aea4
MK
5288 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath)\r
5289 ) == 0)\r
5290 {\r
84f9a9ec
LG
5291 HiiHandle = Database->Handle;\r
5292 break;\r
5293 }\r
5294 }\r
5295 }\r
5296 }\r
5297\r
93e3992d 5298 Status = ConfigAccess->ExtractConfig (\r
5299 ConfigAccess,\r
6e3f5b2a 5300 NULL,\r
84f9a9ec 5301 &Progress,\r
93e3992d 5302 &AccessResults\r
5303 );\r
ae79d2f9 5304 if (EFI_ERROR (Status)) {\r
6e3f5b2a 5305 //\r
d1102dba 5306 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
6e3f5b2a 5307 //\r
1436aea4 5308 if ((HiiHandle != NULL) && (DevicePath != NULL)) {\r
ae79d2f9 5309 IfrDataParsedFlag = TRUE;\r
1436aea4 5310 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
ae79d2f9
LG
5311 //\r
5312 // Get the full request string to get the Current setting again.\r
5313 //\r
1436aea4 5314 if (!EFI_ERROR (Status) && (ConfigRequest != NULL)) {\r
ae79d2f9
LG
5315 Status = ConfigAccess->ExtractConfig (\r
5316 ConfigAccess,\r
5317 ConfigRequest,\r
5318 &Progress,\r
5319 &AccessResults\r
5320 );\r
5321 FreePool (ConfigRequest);\r
5322 } else {\r
5323 Status = EFI_NOT_FOUND;\r
5324 }\r
5325 }\r
5326 }\r
5327\r
5328 if (!EFI_ERROR (Status)) {\r
5329 //\r
d1102dba 5330 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
ae79d2f9 5331 //\r
1436aea4 5332 if (!IfrDataParsedFlag && (HiiHandle != NULL) && (DevicePath != NULL)) {\r
6e3f5b2a
LG
5333 StringPtr = StrStr (AccessResults, L"&GUID=");\r
5334 if (StringPtr != NULL) {\r
5335 *StringPtr = 0;\r
5336 }\r
1436aea4 5337\r
82e8c138 5338 if (GetElementsFromRequest (AccessResults)) {\r
ae79d2f9
LG
5339 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
5340 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a 5341 }\r
1436aea4 5342\r
6e3f5b2a
LG
5343 if (StringPtr != NULL) {\r
5344 *StringPtr = L'&';\r
5345 }\r
5346 }\r
1436aea4 5347\r
84f9a9ec
LG
5348 //\r
5349 // Merge the default sting from IFR code into the got setting from driver.\r
5350 //\r
5351 if (DefaultResults != NULL) {\r
8567300a
LG
5352 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
5353 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 5354 FreePool (DefaultResults);\r
8567300a 5355 DefaultResults = NULL;\r
84f9a9ec 5356 }\r
d1102dba 5357\r
8d00a0f1 5358 //\r
5359 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4a429716 5360 // which separates the first <ConfigAltResp> and the following ones.\r
8d00a0f1 5361 //\r
5362 if (!FirstElement) {\r
5363 Status = AppendToMultiString (Results, L"&");\r
5364 ASSERT_EFI_ERROR (Status);\r
676df92c 5365 }\r
d1102dba 5366\r
8d00a0f1 5367 Status = AppendToMultiString (Results, AccessResults);\r
5368 ASSERT_EFI_ERROR (Status);\r
93e3992d 5369\r
8d00a0f1 5370 FirstElement = FALSE;\r
d1102dba 5371\r
8d00a0f1 5372 FreePool (AccessResults);\r
5373 AccessResults = NULL;\r
5374 }\r
93e3992d 5375 }\r
1436aea4 5376\r
f4113e1f 5377 FreePool (ConfigAccessHandles);\r
93e3992d 5378\r
d1102dba 5379 return EFI_SUCCESS;\r
93e3992d 5380}\r
5381\r
93e3992d 5382/**\r
5383 This function processes the results of processing forms and routes it to the\r
5384 appropriate handlers or storage.\r
5385\r
5386 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5387 instance.\r
5388 @param Configuration A null-terminated Unicode string in\r
5389 <MulltiConfigResp> format.\r
5390 @param Progress A pointer to a string filled in with the offset of\r
5391 the most recent & before the first failing name /\r
5392 value pair (or the beginning of the string if the\r
5393 failure is in the first name / value pair) or the\r
5394 terminating NULL if all was successful.\r
5395\r
5396 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
5397 distribution.\r
5398 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
5399 results that must be stored awaiting possible\r
5400 future protocols.\r
5401 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
5402 would result in this type of error.\r
5403 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
5404 found.\r
5405\r
5406**/\r
5407EFI_STATUS\r
5408EFIAPI\r
813acf3a 5409HiiConfigRoutingRouteConfig (\r
93e3992d 5410 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5411 IN CONST EFI_STRING Configuration,\r
5412 OUT EFI_STRING *Progress\r
5413 )\r
5414{\r
1436aea4
MK
5415 HII_DATABASE_PRIVATE_DATA *Private;\r
5416 EFI_STRING StringPtr;\r
5417 EFI_STRING ConfigResp;\r
5418 UINTN Length;\r
5419 EFI_STATUS Status;\r
5420 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
5421 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
5422 LIST_ENTRY *Link;\r
5423 HII_DATABASE_RECORD *Database;\r
5424 UINT8 *DevicePathPkg;\r
5425 UINT8 *CurrentDevicePath;\r
5426 EFI_HANDLE DriverHandle;\r
5427 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5428 EFI_STRING AccessProgress;\r
5429 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
5430 BOOLEAN IsEfiVarstore;\r
5431 UINTN DevicePathSize;\r
5432\r
5433 if ((This == NULL) || (Progress == NULL)) {\r
93e3992d 5434 return EFI_INVALID_PARAMETER;\r
5435 }\r
5436\r
5437 if (Configuration == NULL) {\r
5438 *Progress = NULL;\r
5439 return EFI_INVALID_PARAMETER;\r
5440 }\r
5441\r
1436aea4
MK
5442 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5443 StringPtr = Configuration;\r
5444 *Progress = StringPtr;\r
5445 Database = NULL;\r
5446 AccessProgress = NULL;\r
5447 EfiVarStoreInfo = NULL;\r
5448 IsEfiVarstore = FALSE;\r
93e3992d 5449\r
5450 //\r
5451 // The first element of <MultiConfigResp> should be\r
5452 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
5453 //\r
5454 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
5455 return EFI_INVALID_PARAMETER;\r
5456 }\r
5457\r
5458 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
5459 //\r
5460 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
5461 // or most recent & before the error.\r
5462 //\r
5463 if (StringPtr == Configuration) {\r
5464 *Progress = StringPtr;\r
5465 } else {\r
5466 *Progress = StringPtr - 1;\r
5467 }\r
5468\r
5469 //\r
5470 // Process each <ConfigResp> of <MultiConfigResp>\r
5471 //\r
1436aea4 5472 Length = CalculateConfigStringLen (StringPtr);\r
93e3992d 5473 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
5474 if (ConfigResp == NULL) {\r
5475 return EFI_OUT_OF_RESOURCES;\r
5476 }\r
1436aea4 5477\r
93e3992d 5478 //\r
5479 // Append '\0' to the end of ConfigRequest\r
5480 //\r
5481 *(ConfigResp + Length) = 0;\r
5482\r
5483 //\r
5484 // Get the UEFI device path\r
5485 //\r
1436aea4 5486 Status = GetDevicePath (ConfigResp, (UINT8 **)&DevicePath);\r
93e3992d 5487 if (EFI_ERROR (Status)) {\r
676df92c 5488 FreePool (ConfigResp);\r
93e3992d 5489 return Status;\r
5490 }\r
5491\r
5492 //\r
84f9a9ec
LG
5493 // Find driver which matches the routing data.\r
5494 //\r
1436aea4 5495 DriverHandle = NULL;\r
84f9a9ec
LG
5496 for (Link = Private->DatabaseList.ForwardLink;\r
5497 Link != &Private->DatabaseList;\r
5498 Link = Link->ForwardLink\r
1436aea4
MK
5499 )\r
5500 {\r
84f9a9ec
LG
5501 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
5502\r
5503 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
5504 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
1436aea4
MK
5505 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);\r
5506 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigResp)) {\r
84f9a9ec
LG
5507 DriverHandle = Database->DriverHandle;\r
5508 break;\r
5509 }\r
5510 }\r
5511 }\r
93e3992d 5512\r
84f9a9ec
LG
5513 //\r
5514 // Try to find driver handle by device path.\r
5515 //\r
5516 if (DriverHandle == NULL) {\r
5517 TempDevicePath = DevicePath;\r
1436aea4
MK
5518 Status = gBS->LocateDevicePath (\r
5519 &gEfiDevicePathProtocolGuid,\r
5520 &TempDevicePath,\r
5521 &DriverHandle\r
5522 );\r
84f9a9ec
LG
5523 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
5524 //\r
5525 // Routing data does not match any known driver.\r
5526 // Set Progress to the 'G' in "GUID" of the routing header.\r
5527 //\r
5528 FreePool (DevicePath);\r
5529 *Progress = StringPtr;\r
5530 FreePool (ConfigResp);\r
5531 return EFI_NOT_FOUND;\r
5532 }\r
93e3992d 5533 }\r
5534\r
84f9a9ec
LG
5535 FreePool (DevicePath);\r
5536\r
93e3992d 5537 //\r
cce6230f 5538 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 5539 //\r
1436aea4 5540 Status = GetVarStoreType (Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
cce6230f
ED
5541 if (EFI_ERROR (Status)) {\r
5542 return Status;\r
5543 }\r
93e3992d 5544\r
cce6230f
ED
5545 if (IsEfiVarstore) {\r
5546 //\r
5547 // Call the SetVariable function to route settings.\r
d1102dba 5548 //\r
1436aea4 5549 Status = RouteConfigRespForEfiVarStore (This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
cce6230f
ED
5550 FreePool (EfiVarStoreInfo);\r
5551 } else {\r
5552 //\r
5553 // Call corresponding ConfigAccess protocol to route settings\r
5554 //\r
5555 Status = gBS->HandleProtocol (\r
5556 DriverHandle,\r
5557 &gEfiHiiConfigAccessProtocolGuid,\r
1436aea4 5558 (VOID **)&ConfigAccess\r
cce6230f 5559 );\r
1f9f60ad
DB
5560 if (EFI_ERROR (Status)) {\r
5561 *Progress = StringPtr;\r
5562 FreePool (ConfigResp);\r
5563 return EFI_NOT_FOUND;\r
5564 }\r
93e3992d 5565\r
cce6230f
ED
5566 Status = ConfigAccess->RouteConfig (\r
5567 ConfigAccess,\r
5568 ConfigResp,\r
5569 &AccessProgress\r
5570 );\r
5571 }\r
1436aea4 5572\r
93e3992d 5573 if (EFI_ERROR (Status)) {\r
523f48e7 5574 ASSERT (AccessProgress != NULL);\r
93e3992d 5575 //\r
5576 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
5577 // Map it to the progress on <MultiConfigResp> then return it.\r
5578 //\r
8d00a0f1 5579 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 5580\r
676df92c 5581 FreePool (ConfigResp);\r
93e3992d 5582 return Status;\r
5583 }\r
5584\r
676df92c 5585 FreePool (ConfigResp);\r
93e3992d 5586 ConfigResp = NULL;\r
5587\r
5588 //\r
5589 // Go to next <ConfigResp> (skip '&').\r
5590 //\r
5591 StringPtr += Length;\r
5592 if (*StringPtr == 0) {\r
5593 *Progress = StringPtr;\r
5594 break;\r
5595 }\r
5596\r
5597 StringPtr++;\r
93e3992d 5598 }\r
5599\r
5600 return EFI_SUCCESS;\r
93e3992d 5601}\r
5602\r
93e3992d 5603/**\r
5604 This helper function is to be called by drivers to map configuration data\r
5605 stored in byte array ("block") formats such as UEFI Variables into current\r
5606 configuration strings.\r
5607\r
5608 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5609 instance.\r
5610 @param ConfigRequest A null-terminated Unicode string in\r
5611 <ConfigRequest> format.\r
5612 @param Block Array of bytes defining the block's configuration.\r
5613 @param BlockSize Length in bytes of Block.\r
5614 @param Config Filled-in configuration string. String allocated\r
5615 by the function. Returned only if call is\r
84f9a9ec 5616 successful. It is <ConfigResp> string format.\r
93e3992d 5617 @param Progress A pointer to a string filled in with the offset of\r
5618 the most recent & before the first failing\r
5619 name/value pair (or the beginning of the string if\r
5620 the failure is in the first name / value pair) or\r
5621 the terminating NULL if all was successful.\r
5622\r
5623 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
5624 terminator at the end of the ConfigRequest\r
5625 string.\r
5626 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
5627 points to the first character of ConfigRequest.\r
5628 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
5629 Block parameter would result in this type of\r
5630 error. Progress points to the first character of\r
5631 ConfigRequest.\r
5632 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
5633 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
5634 Block is left updated and Progress points at\r
5635 the "&" preceding the first non-<BlockName>.\r
5636\r
5637**/\r
5638EFI_STATUS\r
5639EFIAPI\r
5640HiiBlockToConfig (\r
5641 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5642 IN CONST EFI_STRING ConfigRequest,\r
5643 IN CONST UINT8 *Block,\r
5644 IN CONST UINTN BlockSize,\r
5645 OUT EFI_STRING *Config,\r
5646 OUT EFI_STRING *Progress\r
5647 )\r
5648{\r
1436aea4
MK
5649 HII_DATABASE_PRIVATE_DATA *Private;\r
5650 EFI_STRING StringPtr;\r
5651 UINTN Length;\r
5652 EFI_STATUS Status;\r
5653 EFI_STRING TmpPtr;\r
5654 UINT8 *TmpBuffer;\r
5655 UINTN Offset;\r
5656 UINTN Width;\r
5657 UINT8 *Value;\r
5658 EFI_STRING ValueStr;\r
5659 EFI_STRING ConfigElement;\r
5660 UINTN Index;\r
5661 UINT8 *TemBuffer;\r
5662 CHAR16 *TemString;\r
93e3992d 5663\r
4e1005ec
ED
5664 TmpBuffer = NULL;\r
5665\r
1436aea4 5666 if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {\r
93e3992d 5667 return EFI_INVALID_PARAMETER;\r
5668 }\r
5669\r
1436aea4 5670 if ((Block == NULL) || (ConfigRequest == NULL)) {\r
93e3992d 5671 *Progress = ConfigRequest;\r
5672 return EFI_INVALID_PARAMETER;\r
5673 }\r
5674\r
84f9a9ec
LG
5675 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5676 ASSERT (Private != NULL);\r
5677\r
93e3992d 5678 StringPtr = ConfigRequest;\r
5679 ValueStr = NULL;\r
5680 Value = NULL;\r
5681 ConfigElement = NULL;\r
5682\r
5683 //\r
5684 // Allocate a fix length of memory to store Results. Reallocate memory for\r
5685 // Results if this fix length is insufficient.\r
5686 //\r
1436aea4 5687 *Config = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
93e3992d 5688 if (*Config == NULL) {\r
5689 return EFI_OUT_OF_RESOURCES;\r
5690 }\r
5691\r
5692 //\r
5693 // Jump <ConfigHdr>\r
5694 //\r
5695 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
5696 *Progress = StringPtr;\r
1436aea4 5697 Status = EFI_INVALID_PARAMETER;\r
93e3992d 5698 goto Exit;\r
5699 }\r
1436aea4 5700\r
93e3992d 5701 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
5702 StringPtr++;\r
5703 }\r
1436aea4 5704\r
93e3992d 5705 if (*StringPtr == 0) {\r
76c24251 5706 *Progress = StringPtr - 1;\r
1436aea4 5707 Status = EFI_INVALID_PARAMETER;\r
93e3992d 5708 goto Exit;\r
5709 }\r
08e6463a 5710\r
5711 while (*StringPtr != L'&' && *StringPtr != 0) {\r
5712 StringPtr++;\r
5713 }\r
1436aea4 5714\r
08e6463a 5715 if (*StringPtr == 0) {\r
41ff10dc 5716 *Progress = StringPtr;\r
41ff10dc 5717\r
1436aea4 5718 AppendToMultiString (Config, ConfigRequest);\r
41ff10dc
ED
5719 HiiToLower (*Config);\r
5720\r
96179cb3 5721 return EFI_SUCCESS;\r
08e6463a 5722 }\r
1436aea4 5723\r
08e6463a 5724 //\r
5725 // Skip '&'\r
5726 //\r
5727 StringPtr++;\r
93e3992d 5728\r
5729 //\r
5730 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
5731 //\r
c640186e
JB
5732 TemString = AllocateCopyPool (sizeof (CHAR16) * (StringPtr - ConfigRequest + 1), ConfigRequest);\r
5733 if (TemString == NULL) {\r
5734 return EFI_OUT_OF_RESOURCES;\r
5735 }\r
1436aea4 5736\r
c640186e 5737 TemString[StringPtr - ConfigRequest] = '\0';\r
1436aea4 5738 AppendToMultiString (Config, TemString);\r
c640186e 5739 FreePool (TemString);\r
93e3992d 5740\r
5741 //\r
5742 // Parse each <RequestElement> if exists\r
5743 // Only <BlockName> format is supported by this help function.\r
5744 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
5745 //\r
5746 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
5747 //\r
5748 // Back up the header of one <BlockName>\r
5749 //\r
5750 TmpPtr = StringPtr;\r
5751\r
5752 StringPtr += StrLen (L"OFFSET=");\r
5753 //\r
5754 // Get Offset\r
5755 //\r
5756 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 5757 if (EFI_ERROR (Status)) {\r
46c3efbb 5758 *Progress = TmpPtr - 1;\r
93e3992d 5759 goto Exit;\r
5760 }\r
1436aea4 5761\r
93e3992d 5762 Offset = 0;\r
5763 CopyMem (\r
5764 &Offset,\r
5765 TmpBuffer,\r
5766 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5767 );\r
676df92c 5768 FreePool (TmpBuffer);\r
93e3992d 5769\r
5770 StringPtr += Length;\r
5771 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 5772 *Progress = TmpPtr - 1;\r
1436aea4 5773 Status = EFI_INVALID_PARAMETER;\r
93e3992d 5774 goto Exit;\r
5775 }\r
1436aea4 5776\r
93e3992d 5777 StringPtr += StrLen (L"&WIDTH=");\r
5778\r
5779 //\r
5780 // Get Width\r
5781 //\r
5782 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 5783 if (EFI_ERROR (Status)) {\r
46c3efbb 5784 *Progress = TmpPtr - 1;\r
93e3992d 5785 goto Exit;\r
5786 }\r
1436aea4 5787\r
93e3992d 5788 Width = 0;\r
5789 CopyMem (\r
5790 &Width,\r
5791 TmpBuffer,\r
5792 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5793 );\r
676df92c 5794 FreePool (TmpBuffer);\r
93e3992d 5795\r
5796 StringPtr += Length;\r
1436aea4 5797 if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
46c3efbb 5798 *Progress = TmpPtr - 1;\r
1436aea4 5799 Status = EFI_INVALID_PARAMETER;\r
93e3992d 5800 goto Exit;\r
5801 }\r
5802\r
5803 //\r
5804 // Calculate Value and convert it to hex string.\r
5805 //\r
5806 if (Offset + Width > BlockSize) {\r
5807 *Progress = StringPtr;\r
1436aea4 5808 Status = EFI_DEVICE_ERROR;\r
93e3992d 5809 goto Exit;\r
5810 }\r
5811\r
1436aea4 5812 Value = (UINT8 *)AllocateZeroPool (Width);\r
93e3992d 5813 if (Value == NULL) {\r
5814 *Progress = ConfigRequest;\r
1436aea4 5815 Status = EFI_OUT_OF_RESOURCES;\r
93e3992d 5816 goto Exit;\r
5817 }\r
5818\r
1436aea4 5819 CopyMem (Value, (UINT8 *)Block + Offset, Width);\r
93e3992d 5820\r
1436aea4
MK
5821 Length = Width * 2 + 1;\r
5822 ValueStr = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));\r
93e3992d 5823 if (ValueStr == NULL) {\r
5824 *Progress = ConfigRequest;\r
1436aea4 5825 Status = EFI_OUT_OF_RESOURCES;\r
93e3992d 5826 goto Exit;\r
5827 }\r
d1102dba 5828\r
63d55bb9
LG
5829 TemString = ValueStr;\r
5830 TemBuffer = Value + Width - 1;\r
1436aea4 5831 for (Index = 0; Index < Width; Index++, TemBuffer--) {\r
9f4048f7
HW
5832 UnicodeValueToStringS (\r
5833 TemString,\r
5834 Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),\r
5835 PREFIX_ZERO | RADIX_HEX,\r
5836 *TemBuffer,\r
5837 2\r
5838 );\r
5839 TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));\r
63d55bb9 5840 }\r
813acf3a 5841\r
676df92c 5842 FreePool (Value);\r
93e3992d 5843 Value = NULL;\r
5844\r
5845 //\r
5846 // Build a ConfigElement\r
5847 //\r
1436aea4
MK
5848 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
5849 ConfigElement = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));\r
93e3992d 5850 if (ConfigElement == NULL) {\r
5851 Status = EFI_OUT_OF_RESOURCES;\r
5852 goto Exit;\r
5853 }\r
1436aea4 5854\r
93e3992d 5855 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
5856 if (*StringPtr == 0) {\r
5857 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
5858 }\r
1436aea4 5859\r
93e3992d 5860 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
5ad66ec6
DB
5861 StrCatS (ConfigElement, Length, L"VALUE=");\r
5862 StrCatS (ConfigElement, Length, ValueStr);\r
93e3992d 5863\r
5864 AppendToMultiString (Config, ConfigElement);\r
5865\r
676df92c 5866 FreePool (ConfigElement);\r
5867 FreePool (ValueStr);\r
93e3992d 5868 ConfigElement = NULL;\r
1436aea4 5869 ValueStr = NULL;\r
93e3992d 5870\r
5871 //\r
5872 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
5873 //\r
5874 if (*StringPtr == 0) {\r
5875 break;\r
5876 }\r
1436aea4 5877\r
93e3992d 5878 AppendToMultiString (Config, L"&");\r
5879 StringPtr++;\r
93e3992d 5880 }\r
5881\r
5882 if (*StringPtr != 0) {\r
5883 *Progress = StringPtr - 1;\r
1436aea4 5884 Status = EFI_INVALID_PARAMETER;\r
93e3992d 5885 goto Exit;\r
5886 }\r
d1102dba 5887\r
84f9a9ec 5888 HiiToLower (*Config);\r
93e3992d 5889 *Progress = StringPtr;\r
5890 return EFI_SUCCESS;\r
5891\r
5892Exit:\r
76c24251 5893 if (*Config != NULL) {\r
1436aea4
MK
5894 FreePool (*Config);\r
5895 *Config = NULL;\r
76c24251 5896 }\r
1436aea4 5897\r
676df92c 5898 if (ValueStr != NULL) {\r
5899 FreePool (ValueStr);\r
5900 }\r
1436aea4 5901\r
676df92c 5902 if (Value != NULL) {\r
5903 FreePool (Value);\r
5904 }\r
1436aea4 5905\r
69367b5b 5906 if (ConfigElement != NULL) {\r
676df92c 5907 FreePool (ConfigElement);\r
5908 }\r
93e3992d 5909\r
5910 return Status;\r
93e3992d 5911}\r
5912\r
93e3992d 5913/**\r
5914 This helper function is to be called by drivers to map configuration strings\r
5915 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
5916\r
5917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5918 instance.\r
5919 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 5920 format.\r
93e3992d 5921 @param Block A possibly null array of bytes representing the\r
5922 current block. Only bytes referenced in the\r
5923 ConfigResp string in the block are modified. If\r
5924 this parameter is null or if the *BlockSize\r
5925 parameter is (on input) shorter than required by\r
5926 the Configuration string, only the BlockSize\r
5927 parameter is updated and an appropriate status\r
5928 (see below) is returned.\r
5929 @param BlockSize The length of the Block in units of UINT8. On\r
5930 input, this is the size of the Block. On output,\r
c0a3c3da
ED
5931 if successful, contains the largest index of the\r
5932 modified byte in the Block, or the required buffer\r
5933 size if the Block is not large enough.\r
93e3992d 5934 @param Progress On return, points to an element of the ConfigResp\r
5935 string filled in with the offset of the most\r
5936 recent '&' before the first failing name / value\r
5937 pair (or the beginning of the string if the\r
5938 failure is in the first name / value pair) or the\r
5939 terminating NULL if all was successful.\r
5940\r
5941 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
5942 terminator at the end of the ConfigResp string.\r
5943 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
5944 points to the first character of ConfigResp.\r
5945 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
5946 Block parameter would result in this type of\r
5947 error. Progress points to the first character of\r
5948 ConfigResp.\r
5949 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
5950 value pair. Block is left updated and\r
5951 Progress points at the '&' preceding the first\r
5952 non-<BlockName>.\r
d1102dba 5953 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.\r
c0a3c3da 5954 BlockSize is updated with the required buffer size.\r
09b79417
LG
5955 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
5956 Progress points to the "G" in "GUID" of the errant\r
5957 routing data.\r
93e3992d 5958\r
5959**/\r
5960EFI_STATUS\r
5961EFIAPI\r
5962HiiConfigToBlock (\r
1436aea4
MK
5963 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5964 IN CONST EFI_STRING ConfigResp,\r
5965 IN OUT UINT8 *Block,\r
5966 IN OUT UINTN *BlockSize,\r
5967 OUT EFI_STRING *Progress\r
93e3992d 5968 )\r
5969{\r
1436aea4
MK
5970 HII_DATABASE_PRIVATE_DATA *Private;\r
5971 EFI_STRING StringPtr;\r
5972 EFI_STRING TmpPtr;\r
5973 UINTN Length;\r
5974 EFI_STATUS Status;\r
5975 UINT8 *TmpBuffer;\r
5976 UINTN Offset;\r
5977 UINTN Width;\r
5978 UINT8 *Value;\r
5979 UINTN BufferSize;\r
5980 UINTN MaxBlockSize;\r
93e3992d 5981\r
4e1005ec
ED
5982 TmpBuffer = NULL;\r
5983\r
1436aea4 5984 if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {\r
93e3992d 5985 return EFI_INVALID_PARAMETER;\r
5986 }\r
5987\r
09b79417
LG
5988 *Progress = ConfigResp;\r
5989 if (ConfigResp == NULL) {\r
93e3992d 5990 return EFI_INVALID_PARAMETER;\r
5991 }\r
5992\r
5993 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5994 ASSERT (Private != NULL);\r
5995\r
1436aea4
MK
5996 StringPtr = ConfigResp;\r
5997 BufferSize = *BlockSize;\r
5998 Value = NULL;\r
09b79417 5999 MaxBlockSize = 0;\r
93e3992d 6000\r
6001 //\r
6002 // Jump <ConfigHdr>\r
6003 //\r
6004 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
6005 *Progress = StringPtr;\r
1436aea4 6006 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6007 goto Exit;\r
6008 }\r
1436aea4 6009\r
93e3992d 6010 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
6011 StringPtr++;\r
6012 }\r
1436aea4 6013\r
93e3992d 6014 if (*StringPtr == 0) {\r
6015 *Progress = StringPtr;\r
1436aea4 6016 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6017 goto Exit;\r
6018 }\r
08e6463a 6019\r
6020 while (*StringPtr != L'&' && *StringPtr != 0) {\r
6021 StringPtr++;\r
6022 }\r
1436aea4 6023\r
08e6463a 6024 if (*StringPtr == 0) {\r
6025 *Progress = StringPtr;\r
1436aea4 6026 Status = EFI_INVALID_PARAMETER;\r
08e6463a 6027 goto Exit;\r
6028 }\r
93e3992d 6029\r
6030 //\r
6031 // Parse each <ConfigElement> if exists\r
edae8d2d 6032 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 6033 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
6034 //\r
edae8d2d 6035 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
46c3efbb 6036 TmpPtr = StringPtr;\r
edae8d2d 6037 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 6038 //\r
6039 // Get Offset\r
6040 //\r
6041 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 6042 if (EFI_ERROR (Status)) {\r
46c3efbb 6043 *Progress = TmpPtr;\r
93e3992d 6044 goto Exit;\r
6045 }\r
1436aea4 6046\r
93e3992d 6047 Offset = 0;\r
6048 CopyMem (\r
6049 &Offset,\r
6050 TmpBuffer,\r
6051 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
6052 );\r
676df92c 6053 FreePool (TmpBuffer);\r
93e3992d 6054\r
6055 StringPtr += Length;\r
6056 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 6057 *Progress = TmpPtr;\r
1436aea4 6058 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6059 goto Exit;\r
6060 }\r
1436aea4 6061\r
93e3992d 6062 StringPtr += StrLen (L"&WIDTH=");\r
6063\r
6064 //\r
6065 // Get Width\r
6066 //\r
6067 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 6068 if (EFI_ERROR (Status)) {\r
46c3efbb 6069 *Progress = TmpPtr;\r
93e3992d 6070 goto Exit;\r
6071 }\r
1436aea4 6072\r
93e3992d 6073 Width = 0;\r
6074 CopyMem (\r
6075 &Width,\r
6076 TmpBuffer,\r
6077 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
6078 );\r
676df92c 6079 FreePool (TmpBuffer);\r
93e3992d 6080\r
6081 StringPtr += Length;\r
6082 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
46c3efbb 6083 *Progress = TmpPtr;\r
1436aea4 6084 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6085 goto Exit;\r
6086 }\r
1436aea4 6087\r
93e3992d 6088 StringPtr += StrLen (L"&VALUE=");\r
6089\r
6090 //\r
6091 // Get Value\r
6092 //\r
6093 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 6094 if (EFI_ERROR (Status)) {\r
46c3efbb 6095 *Progress = TmpPtr;\r
93e3992d 6096 goto Exit;\r
6097 }\r
6098\r
6099 StringPtr += Length;\r
1436aea4 6100 if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
46c3efbb 6101 *Progress = TmpPtr;\r
1436aea4 6102 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6103 goto Exit;\r
6104 }\r
6105\r
6106 //\r
6107 // Update the Block with configuration info\r
6108 //\r
09b79417
LG
6109 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
6110 CopyMem (Block + Offset, Value, Width);\r
6111 }\r
1436aea4 6112\r
09b79417
LG
6113 if (Offset + Width > MaxBlockSize) {\r
6114 MaxBlockSize = Offset + Width;\r
93e3992d 6115 }\r
93e3992d 6116\r
676df92c 6117 FreePool (Value);\r
93e3992d 6118 Value = NULL;\r
6119\r
6120 //\r
edae8d2d 6121 // If '\0', parsing is finished.\r
93e3992d 6122 //\r
6123 if (*StringPtr == 0) {\r
6124 break;\r
6125 }\r
93e3992d 6126 }\r
d1102dba 6127\r
84f9a9ec 6128 //\r
edae8d2d 6129 // The input string is not ConfigResp format, return error.\r
84f9a9ec 6130 //\r
edae8d2d
ED
6131 if (*StringPtr != 0) {\r
6132 *Progress = StringPtr;\r
1436aea4 6133 Status = EFI_INVALID_PARAMETER;\r
93e3992d 6134 goto Exit;\r
6135 }\r
6136\r
1436aea4 6137 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
6138 *BlockSize = MaxBlockSize - 1;\r
6139\r
6140 if (MaxBlockSize > BufferSize) {\r
6141 *BlockSize = MaxBlockSize;\r
9ac0640d 6142 if (Block != NULL) {\r
c0a3c3da 6143 return EFI_BUFFER_TOO_SMALL;\r
09b79417
LG
6144 }\r
6145 }\r
6146\r
9ac0640d
LG
6147 if (Block == NULL) {\r
6148 *Progress = ConfigResp;\r
6149 return EFI_INVALID_PARAMETER;\r
6150 }\r
6151\r
93e3992d 6152 return EFI_SUCCESS;\r
6153\r
6154Exit:\r
6155\r
676df92c 6156 if (Value != NULL) {\r
6157 FreePool (Value);\r
6158 }\r
1436aea4 6159\r
93e3992d 6160 return Status;\r
6161}\r
6162\r
93e3992d 6163/**\r
6164 This helper function is to be called by drivers to extract portions of\r
6165 a larger configuration string.\r
6166\r
6167 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
6168 instance.\r
6169 @param Configuration A null-terminated Unicode string in\r
771ececd 6170 <MultiConfigAltResp> format.\r
93e3992d 6171 @param Guid A pointer to the GUID value to search for in the\r
6172 routing portion of the ConfigResp string when\r
6173 retrieving the requested data. If Guid is NULL,\r
6174 then all GUID values will be searched for.\r
6175 @param Name A pointer to the NAME value to search for in the\r
6176 routing portion of the ConfigResp string when\r
6177 retrieving the requested data. If Name is NULL,\r
6178 then all Name values will be searched for.\r
6179 @param DevicePath A pointer to the PATH value to search for in the\r
6180 routing portion of the ConfigResp string when\r
6181 retrieving the requested data. If DevicePath is\r
6182 NULL, then all DevicePath values will be searched\r
6183 for.\r
6184 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
6185 routing portion of the ConfigResp string when\r
6186 retrieving the requested data. If this parameter\r
6187 is NULL, then the current setting will be\r
6188 retrieved.\r
6189 @param AltCfgResp A pointer to a buffer which will be allocated by\r
6190 the function which contains the retrieved string\r
6191 as requested. This buffer is only allocated if\r
84f9a9ec 6192 the call was successful. It is <ConfigResp> format.\r
93e3992d 6193\r
6194 @retval EFI_SUCCESS The request succeeded. The requested data was\r
6195 extracted and placed in the newly allocated\r
6196 AltCfgResp buffer.\r
6197 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
6198 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
6199 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
6200 found.\r
6201\r
6202**/\r
6203EFI_STATUS\r
6204EFIAPI\r
6205HiiGetAltCfg (\r
1436aea4
MK
6206 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
6207 IN CONST EFI_STRING Configuration,\r
6208 IN CONST EFI_GUID *Guid,\r
6209 IN CONST EFI_STRING Name,\r
6210 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
6211 IN CONST UINT16 *AltCfgId,\r
6212 OUT EFI_STRING *AltCfgResp\r
93e3992d 6213 )\r
6214{\r
1436aea4
MK
6215 EFI_STATUS Status;\r
6216 EFI_STRING StringPtr;\r
6217 EFI_STRING HdrStart;\r
6218 EFI_STRING HdrEnd;\r
6219 EFI_STRING TmpPtr;\r
6220 UINTN Length;\r
6221 EFI_STRING GuidStr;\r
6222 EFI_STRING NameStr;\r
6223 EFI_STRING PathStr;\r
6224 EFI_STRING AltIdStr;\r
6225 EFI_STRING Result;\r
6226 BOOLEAN GuidFlag;\r
6227 BOOLEAN NameFlag;\r
6228 BOOLEAN PathFlag;\r
e90b081a 6229\r
6230 HdrStart = NULL;\r
6231 HdrEnd = NULL;\r
6232 GuidStr = NULL;\r
6233 NameStr = NULL;\r
6234 PathStr = NULL;\r
6235 AltIdStr = NULL;\r
6236 Result = NULL;\r
6237 GuidFlag = FALSE;\r
6238 NameFlag = FALSE;\r
6239 PathFlag = FALSE;\r
93e3992d 6240\r
1436aea4 6241 if ((This == NULL) || (Configuration == NULL) || (AltCfgResp == NULL)) {\r
93e3992d 6242 return EFI_INVALID_PARAMETER;\r
6243 }\r
6244\r
6245 StringPtr = Configuration;\r
6246 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
6247 return EFI_INVALID_PARAMETER;\r
6248 }\r
6249\r
6250 //\r
6251 // Generate the sub string for later matching.\r
6252 //\r
1436aea4 6253 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)Guid, 1, &GuidStr);\r
93e3992d 6254 GenerateSubStr (\r
6255 L"PATH=",\r
1436aea4
MK
6256 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),\r
6257 (VOID *)DevicePath,\r
813acf3a 6258 1,\r
93e3992d 6259 &PathStr\r
6260 );\r
6261 if (AltCfgId != NULL) {\r
1436aea4 6262 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *)AltCfgId, 3, &AltIdStr);\r
93e3992d 6263 }\r
1436aea4 6264\r
93e3992d 6265 if (Name != NULL) {\r
1436aea4 6266 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);\r
93e3992d 6267 } else {\r
813acf3a 6268 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 6269 }\r
6270\r
6271 while (*StringPtr != 0) {\r
6272 //\r
6273 // Try to match the GUID\r
6274 //\r
6275 if (!GuidFlag) {\r
6276 TmpPtr = StrStr (StringPtr, GuidStr);\r
6277 if (TmpPtr == NULL) {\r
6278 Status = EFI_NOT_FOUND;\r
6279 goto Exit;\r
6280 }\r
1436aea4 6281\r
93e3992d 6282 HdrStart = TmpPtr;\r
6283\r
6284 //\r
6285 // Jump to <NameHdr>\r
6286 //\r
6287 if (Guid != NULL) {\r
6288 StringPtr = TmpPtr + StrLen (GuidStr);\r
6289 } else {\r
6290 StringPtr = StrStr (TmpPtr, L"NAME=");\r
6291 if (StringPtr == NULL) {\r
6292 Status = EFI_NOT_FOUND;\r
6293 goto Exit;\r
6294 }\r
6295 }\r
1436aea4 6296\r
93e3992d 6297 GuidFlag = TRUE;\r
6298 }\r
6299\r
6300 //\r
6301 // Try to match the NAME\r
6302 //\r
6303 if (GuidFlag && !NameFlag) {\r
6304 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
6305 GuidFlag = FALSE;\r
6306 } else {\r
6307 //\r
6308 // Jump to <PathHdr>\r
6309 //\r
6310 if (Name != NULL) {\r
6311 StringPtr += StrLen (NameStr);\r
6312 } else {\r
6313 StringPtr = StrStr (StringPtr, L"PATH=");\r
6314 if (StringPtr == NULL) {\r
6315 Status = EFI_NOT_FOUND;\r
6316 goto Exit;\r
6317 }\r
6318 }\r
1436aea4 6319\r
93e3992d 6320 NameFlag = TRUE;\r
6321 }\r
6322 }\r
6323\r
6324 //\r
6325 // Try to match the DevicePath\r
6326 //\r
6327 if (GuidFlag && NameFlag && !PathFlag) {\r
6328 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
6329 GuidFlag = FALSE;\r
6330 NameFlag = FALSE;\r
6331 } else {\r
6332 //\r
6333 // Jump to '&' before <DescHdr> or <ConfigBody>\r
6334 //\r
6335 if (DevicePath != NULL) {\r
6336 StringPtr += StrLen (PathStr);\r
6337 } else {\r
6338 StringPtr = StrStr (StringPtr, L"&");\r
6339 if (StringPtr == NULL) {\r
6340 Status = EFI_NOT_FOUND;\r
6341 goto Exit;\r
6342 }\r
1436aea4
MK
6343\r
6344 StringPtr++;\r
93e3992d 6345 }\r
1436aea4 6346\r
93e3992d 6347 PathFlag = TRUE;\r
84f9a9ec 6348 HdrEnd = StringPtr;\r
93e3992d 6349 }\r
6350 }\r
6351\r
6352 //\r
6353 // Try to match the AltCfgId\r
6354 //\r
6355 if (GuidFlag && NameFlag && PathFlag) {\r
6356 if (AltCfgId == NULL) {\r
6357 //\r
6358 // Return Current Setting when AltCfgId is NULL.\r
6359 //\r
6360 Status = OutputConfigBody (StringPtr, &Result);\r
6361 goto Exit;\r
6362 }\r
1436aea4 6363\r
93e3992d 6364 //\r
6365 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
6366 //\r
6367 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
6368 GuidFlag = FALSE;\r
6369 NameFlag = FALSE;\r
6370 PathFlag = FALSE;\r
6371 } else {\r
84f9a9ec
LG
6372 //\r
6373 // Skip AltIdStr and &\r
6374 //\r
6375 StringPtr = StringPtr + StrLen (AltIdStr);\r
6376 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 6377 goto Exit;\r
6378 }\r
6379 }\r
6380 }\r
6381\r
6382 Status = EFI_NOT_FOUND;\r
6383\r
6384Exit:\r
76c24251 6385 *AltCfgResp = NULL;\r
bc166db3 6386 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 6387 //\r
6388 // Copy the <ConfigHdr> and <ConfigBody>\r
6389 //\r
1436aea4 6390 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 6391 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
6392 if (*AltCfgResp == NULL) {\r
6393 Status = EFI_OUT_OF_RESOURCES;\r
6394 } else {\r
5ad66ec6
DB
6395 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);\r
6396 StrCatS (*AltCfgResp, Length, Result);\r
93e3992d 6397 Status = EFI_SUCCESS;\r
6398 }\r
6399 }\r
6400\r
676df92c 6401 if (GuidStr != NULL) {\r
6402 FreePool (GuidStr);\r
6403 }\r
1436aea4 6404\r
676df92c 6405 if (NameStr != NULL) {\r
6406 FreePool (NameStr);\r
6407 }\r
1436aea4 6408\r
676df92c 6409 if (PathStr != NULL) {\r
6410 FreePool (PathStr);\r
6411 }\r
1436aea4 6412\r
676df92c 6413 if (AltIdStr != NULL) {\r
6414 FreePool (AltIdStr);\r
6415 }\r
1436aea4 6416\r
676df92c 6417 if (Result != NULL) {\r
6418 FreePool (Result);\r
6419 }\r
93e3992d 6420\r
6421 return Status;\r
93e3992d 6422}\r