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