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