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