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