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