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