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