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