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