]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
ShellPkg: Add missing header files
[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
96179cb3 4Copyright (c) 2007 - 2014, 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
0f83ac34 1290 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {\r
7248790e
ED
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
7248790e
ED
1435\r
1436 default:\r
1437 break;\r
1438 }\r
1439 }\r
7248790e
ED
1440Done:\r
1441 if (HiiFormPackage != NULL) {\r
1442 FreePool (HiiFormPackage);\r
1443 }\r
1444\r
1445 if (VarStoreName != NULL) {\r
1446 FreePool (VarStoreName);\r
1447 }\r
1448\r
1449 return FindVarstore;\r
1450}\r
1451\r
82e8c138
ED
1452/**\r
1453 Check whether the this op code is required.\r
1454\r
1455 @param RequestBlockArray The array includes all the request info or NULL.\r
1456 @param HiiHandle The hii handle for this form package.\r
1457 @param VarStorageData The varstore data strucure.\r
1458 @param IfrOpHdr Ifr opcode header for this opcode.\r
1459 @param VarWidth The buffer width for this opcode.\r
1460 @param ReturnData The data block added for this opcode.\r
1461\r
1462 @retval EFI_SUCCESS This opcode is required.\r
1463 @retval Others This opcode is not required or error occur.\r
1464 \r
1465**/\r
1466EFI_STATUS\r
1467IsThisOpcodeRequired (\r
1468 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1469 IN EFI_HII_HANDLE HiiHandle,\r
1470 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
1471 IN EFI_IFR_OP_HEADER *IfrOpHdr,\r
1472 IN UINT16 VarWidth,\r
1473 OUT IFR_BLOCK_DATA **ReturnData\r
1474 )\r
1475{\r
1476 IFR_BLOCK_DATA *BlockData;\r
1477 UINT16 VarOffset;\r
1478 EFI_STRING_ID NameId;\r
1479 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
1480\r
1481 NameId = 0;\r
1482 VarOffset = 0;\r
1483 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));\r
1484\r
1485 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1486 NameId = IfrQuestionHdr->VarStoreInfo.VarName;\r
1487\r
1488 //\r
1489 // Check whether this question is in requested block array.\r
1490 //\r
1491 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {\r
1492 //\r
1493 // This question is not in the requested string. Skip it.\r
1494 //\r
1495 return EFI_SUCCESS;\r
1496 }\r
1497 } else {\r
1498 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
1499 \r
1500 //\r
1501 // Check whether this question is in requested block array.\r
1502 //\r
1503 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {\r
1504 //\r
1505 // This question is not in the requested string. Skip it.\r
1506 //\r
1507 return EFI_SUCCESS;\r
1508 }\r
1509\r
1510 //\r
1511 // Check this var question is in the var storage \r
1512 //\r
1513 if (((VarOffset + VarWidth) > VarStorageData->Size)) {\r
1514 return EFI_INVALID_PARAMETER;\r
1515 }\r
1516 }\r
1517\r
1518 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1519 if (BlockData == NULL) {\r
1520 return EFI_OUT_OF_RESOURCES;\r
1521 }\r
1522\r
1523 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1524 BlockData->Name = InternalGetString(HiiHandle, NameId);\r
1525 } else {\r
1526 BlockData->Offset = VarOffset;\r
1527 }\r
1528\r
1529 BlockData->Width = VarWidth;\r
1530 BlockData->QuestionId = IfrQuestionHdr->QuestionId;\r
1531 BlockData->OpCode = IfrOpHdr->OpCode;\r
1532 BlockData->Scope = IfrOpHdr->Scope;\r
1533 InitializeListHead (&BlockData->DefaultValueEntry);\r
1534 //\r
1535 // Add Block Data into VarStorageData BlockEntry\r
1536 //\r
1537 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1538 *ReturnData = BlockData;\r
1539\r
1540 return EFI_SUCCESS;\r
1541}\r
1542\r
84f9a9ec
LG
1543/**\r
1544 This function parses Form Package to get the block array and the default\r
1545 value array according to the request ConfigHdr.\r
1546\r
82e8c138 1547 @param HiiHandle Hii Handle for this hii package.\r
84f9a9ec
LG
1548 @param Package Pointer to the form package data.\r
1549 @param PackageLength Length of the pacakge.\r
1550 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1551 the first found varstore will be as ConfigHdr.\r
1552 @param RequestBlockArray The block array is retrieved from the request string.\r
1553 @param VarStorageData VarStorage structure contains the got block and default value.\r
82e8c138 1554 @param DefaultIdArray Point to the got default id and default name array.\r
84f9a9ec
LG
1555\r
1556 @retval EFI_SUCCESS The block array and the default value array are got.\r
1557 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
1558 are conflicted. \r
1559 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
1560**/\r
1561EFI_STATUS\r
1562EFIAPI\r
1563ParseIfrData (\r
82e8c138 1564 IN EFI_HII_HANDLE HiiHandle,\r
84f9a9ec 1565 IN UINT8 *Package,\r
aa75dfec 1566 IN UINT32 PackageLength,\r
84f9a9ec
LG
1567 IN EFI_STRING ConfigHdr,\r
1568 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1569 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
8567300a 1570 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
84f9a9ec
LG
1571 )\r
1572{\r
1573 EFI_STATUS Status;\r
1574 UINTN IfrOffset;\r
22031c4f 1575 UINTN PackageOffset;\r
84f9a9ec 1576 EFI_IFR_VARSTORE *IfrVarStore;\r
cce6230f 1577 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
84f9a9ec
LG
1578 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1579 EFI_IFR_ONE_OF *IfrOneOf;\r
e7fd76d1 1580 EFI_IFR_REF4 *IfrRef;\r
84f9a9ec
LG
1581 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
1582 EFI_IFR_DEFAULT *IfrDefault;\r
1583 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
1584 EFI_IFR_CHECKBOX *IfrCheckBox;\r
1585 EFI_IFR_PASSWORD *IfrPassword;\r
1586 EFI_IFR_STRING *IfrString;\r
d9bbabfd
ED
1587 EFI_IFR_DATE *IfrDate;\r
1588 EFI_IFR_TIME *IfrTime;\r
ef40f0f6
ED
1589 IFR_DEFAULT_DATA DefaultData;\r
1590 IFR_DEFAULT_DATA *DefaultDataPtr;\r
84f9a9ec 1591 IFR_BLOCK_DATA *BlockData;\r
40ae09a2
ED
1592 CHAR16 *VarStoreName;\r
1593 UINT16 VarWidth;\r
1594 UINT16 VarDefaultId;\r
40ae09a2
ED
1595 BOOLEAN FirstOneOfOption;\r
1596 LIST_ENTRY *LinkData;\r
1597 LIST_ENTRY *LinkDefault;\r
1598 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
22031c4f
ED
1599 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
1600 EFI_VARSTORE_ID VarStoreId;\r
40ae09a2 1601\r
40ae09a2 1602 Status = EFI_SUCCESS;\r
40ae09a2
ED
1603 BlockData = NULL;\r
1604 DefaultDataPtr = NULL;\r
1605 FirstOneOfOption = FALSE;\r
22031c4f 1606 VarStoreId = 0;\r
ef40f0f6 1607 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
84f9a9ec
LG
1608\r
1609 //\r
1610 // Go through the form package to parse OpCode one by one.\r
1611 //\r
22031c4f
ED
1612 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1613 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;\r
1614 IfrOffset = PackageOffset;\r
aa75dfec 1615 while (IfrOffset < PackageLength) {\r
22031c4f
ED
1616\r
1617 //\r
1618 // More than one form package found.\r
1619 //\r
1620 if (PackageOffset >= PackageHeader->Length) {\r
1621 //\r
1622 // Already found varstore for this request, break;\r
1623 //\r
1624 if (VarStoreId != 0) {\r
1625 VarStoreId = 0;\r
1626 }\r
1627\r
1628 //\r
1629 // Get next package header info.\r
1630 //\r
1631 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);\r
1632 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1633 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);\r
1634 }\r
1635\r
84f9a9ec 1636 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
84f9a9ec
LG
1637 switch (IfrOpHdr->OpCode) {\r
1638 case EFI_IFR_VARSTORE_OP:\r
1639 //\r
1640 // VarStore is found. Don't need to search any more.\r
1641 //\r
22031c4f 1642 if (VarStoreId != 0) {\r
84f9a9ec
LG
1643 break;\r
1644 }\r
1645\r
84f9a9ec 1646 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
82e8c138 1647\r
f8920f0d 1648 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
84f9a9ec
LG
1649 if (VarStoreName == NULL) {\r
1650 Status = EFI_OUT_OF_RESOURCES;\r
1651 goto Done;\r
1652 }\r
f8920f0d 1653 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);\r
84f9a9ec 1654\r
82e8c138 1655 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
84f9a9ec
LG
1656 //\r
1657 // Find the matched VarStore\r
1658 //\r
1659 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
84f9a9ec
LG
1660 VarStorageData->Size = IfrVarStore->Size;\r
1661 VarStorageData->Name = VarStoreName;\r
82e8c138 1662 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
22031c4f 1663 VarStoreId = IfrVarStore->VarStoreId;\r
84f9a9ec 1664 }\r
84f9a9ec
LG
1665 break;\r
1666\r
cce6230f
ED
1667 case EFI_IFR_VARSTORE_EFI_OP:\r
1668 //\r
1669 // VarStore is found. Don't need to search any more.\r
1670 //\r
22031c4f 1671 if (VarStoreId != 0) {\r
cce6230f
ED
1672 break;\r
1673 }\r
1674\r
cce6230f
ED
1675 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1676\r
1677 //\r
1678 // If the length is small than the structure, this is from old efi \r
1679 // varstore definition. Old efi varstore get config directly from \r
1680 // GetVariable function.\r
1681 // \r
1682 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1683 break;\r
1684 }\r
1685\r
f8920f0d 1686 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
cce6230f
ED
1687 if (VarStoreName == NULL) {\r
1688 Status = EFI_OUT_OF_RESOURCES;\r
1689 goto Done;\r
1690 }\r
f8920f0d 1691 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);\r
cce6230f 1692\r
82e8c138 1693 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
cce6230f
ED
1694 //\r
1695 // Find the matched VarStore\r
1696 //\r
1697 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
cce6230f
ED
1698 VarStorageData->Size = IfrEfiVarStore->Size;\r
1699 VarStorageData->Name = VarStoreName;\r
82e8c138 1700 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
22031c4f 1701 VarStoreId = IfrEfiVarStore->VarStoreId;\r
cce6230f 1702 }\r
cce6230f
ED
1703 break;\r
1704\r
82e8c138 1705 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
84f9a9ec 1706 //\r
82e8c138
ED
1707 // VarStore is found. Don't need to search any more.\r
1708 //\r
22031c4f 1709 if (VarStoreId != 0) {\r
82e8c138
ED
1710 break;\r
1711 }\r
1712\r
1713 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1714\r
1715 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
1716 //\r
1717 // Find the matched VarStore\r
1718 //\r
1719 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);\r
82e8c138 1720 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
22031c4f 1721 VarStoreId = IfrNameValueVarStore->VarStoreId;\r
82e8c138
ED
1722 }\r
1723 break;\r
1724\r
1725 case EFI_IFR_DEFAULTSTORE_OP:\r
1726 //\r
1727 // Add new the map between default id and default name.\r
84f9a9ec 1728 //\r
ef40f0f6
ED
1729 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1730 if (DefaultDataPtr == NULL) {\r
84f9a9ec
LG
1731 Status = EFI_OUT_OF_RESOURCES;\r
1732 goto Done;\r
1733 }\r
ef40f0f6
ED
1734 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
1735 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
1736 DefaultDataPtr = NULL;\r
84f9a9ec
LG
1737 break;\r
1738\r
1739 case EFI_IFR_FORM_OP:\r
2573712e 1740 case EFI_IFR_FORM_MAP_OP:\r
84f9a9ec
LG
1741 //\r
1742 // No matched varstore is found and directly return.\r
1743 //\r
22031c4f 1744 if ( VarStoreId == 0) {\r
84f9a9ec
LG
1745 Status = EFI_SUCCESS;\r
1746 goto Done;\r
1747 }\r
1748 break;\r
1749\r
e7fd76d1
ED
1750 case EFI_IFR_REF_OP:\r
1751 //\r
1752 // Ref question is not in IFR Form. This IFR form is not valid. \r
1753 //\r
22031c4f 1754 if ( VarStoreId == 0) {\r
e7fd76d1
ED
1755 Status = EFI_INVALID_PARAMETER;\r
1756 goto Done;\r
1757 }\r
1758 //\r
1759 // Check whether this question is for the requested varstore.\r
1760 //\r
1761 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
22031c4f 1762 if (IfrRef->Question.VarStoreId != VarStoreId) {\r
e7fd76d1
ED
1763 break;\r
1764 }\r
e7fd76d1 1765 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
e7fd76d1 1766\r
82e8c138
ED
1767 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1768 if (EFI_ERROR (Status)) {\r
e7fd76d1
ED
1769 goto Done;\r
1770 }\r
e7fd76d1
ED
1771 break;\r
1772\r
84f9a9ec
LG
1773 case EFI_IFR_ONE_OF_OP:\r
1774 case EFI_IFR_NUMERIC_OP:\r
1775 //\r
1776 // Numeric and OneOf has the same opcode structure.\r
1777 //\r
1778\r
8567300a
LG
1779 //\r
1780 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
1781 //\r
22031c4f 1782 if (VarStoreId == 0) {\r
8567300a
LG
1783 Status = EFI_INVALID_PARAMETER;\r
1784 goto Done;\r
1785 }\r
84f9a9ec
LG
1786 //\r
1787 // Check whether this question is for the requested varstore.\r
1788 //\r
1789 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
22031c4f 1790 if (IfrOneOf->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
1791 break;\r
1792 }\r
84f9a9ec 1793 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
84f9a9ec 1794\r
82e8c138
ED
1795 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1796 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1797 goto Done;\r
1798 }\r
82e8c138 1799\r
84f9a9ec 1800 if (BlockData == NULL) {\r
82e8c138
ED
1801 //\r
1802 // BlockData == NULL means this opcode is not in the requst array.\r
1803 //\r
1804 break;\r
84f9a9ec 1805 }\r
82e8c138 1806\r
cf4c5a42
LG
1807 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
1808 //\r
1809 // Set this flag to TRUE for the first oneof option.\r
1810 //\r
1811 FirstOneOfOption = TRUE;\r
1812 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
1813 //\r
1814 // Numeric minimum value will be used as default value when no default is specified. \r
1815 //\r
eb5e7d3e 1816 DefaultData.Type = DefaultValueFromDefault;\r
cf4c5a42
LG
1817 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1818 case EFI_IFR_NUMERIC_SIZE_1:\r
e7fd76d1 1819 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
cf4c5a42 1820 break;\r
82e8c138 1821\r
cf4c5a42 1822 case EFI_IFR_NUMERIC_SIZE_2:\r
e7fd76d1 1823 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
cf4c5a42 1824 break;\r
82e8c138 1825\r
cf4c5a42 1826 case EFI_IFR_NUMERIC_SIZE_4:\r
e7fd76d1 1827 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
cf4c5a42 1828 break;\r
82e8c138 1829\r
cf4c5a42 1830 case EFI_IFR_NUMERIC_SIZE_8:\r
e7fd76d1 1831 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
cf4c5a42 1832 break;\r
82e8c138
ED
1833\r
1834 default:\r
1835 Status = EFI_INVALID_PARAMETER;\r
1836 goto Done;\r
cf4c5a42
LG
1837 }\r
1838 //\r
ef40f0f6
ED
1839 // Set default value base on the DefaultId list get from IFR data.\r
1840 // \r
1841 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
82e8c138 1842 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
ef40f0f6
ED
1843 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1844 InsertDefaultValue (BlockData, &DefaultData);\r
1845 }\r
cf4c5a42 1846 }\r
84f9a9ec
LG
1847 break;\r
1848\r
1849 case EFI_IFR_ORDERED_LIST_OP:\r
1850 //\r
1851 // offset by question header\r
1852 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1853 // no default value and default id, how to define its default value?\r
1854 //\r
8567300a
LG
1855\r
1856 //\r
1857 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1858 //\r
22031c4f 1859 if (VarStoreId == 0) {\r
8567300a
LG
1860 Status = EFI_INVALID_PARAMETER;\r
1861 goto Done;\r
1862 }\r
84f9a9ec
LG
1863 //\r
1864 // Check whether this question is for the requested varstore.\r
1865 //\r
1866 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
22031c4f 1867 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {\r
ff28420b 1868 BlockData = NULL;\r
84f9a9ec
LG
1869 break;\r
1870 }\r
84f9a9ec 1871 VarWidth = IfrOrderedList->MaxContainers;\r
82e8c138
ED
1872 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1873 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1874 goto Done;\r
1875 }\r
84f9a9ec
LG
1876 break;\r
1877\r
1878 case EFI_IFR_CHECKBOX_OP:\r
1879 //\r
1880 // EFI_IFR_DEFAULT_OP\r
1881 // offset by question header\r
1882 // width is 1 sizeof (BOOLEAN)\r
1883 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1884 // value by DefaultOption\r
1885 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1886 // \r
1887\r
8567300a
LG
1888 //\r
1889 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1890 //\r
22031c4f 1891 if (VarStoreId == 0) {\r
8567300a
LG
1892 Status = EFI_INVALID_PARAMETER;\r
1893 goto Done;\r
1894 }\r
84f9a9ec
LG
1895 //\r
1896 // Check whether this question is for the requested varstore.\r
1897 //\r
1898 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
22031c4f 1899 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
1900 break;\r
1901 }\r
c9325700 1902 VarWidth = (UINT16) sizeof (BOOLEAN);\r
82e8c138
ED
1903 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1904 if (EFI_ERROR (Status)) {\r
1905 goto Done;\r
1906 }\r
84f9a9ec 1907\r
82e8c138 1908 if (BlockData == NULL) {\r
84f9a9ec 1909 //\r
82e8c138 1910 // BlockData == NULL means this opcode is not in the requst array.\r
84f9a9ec
LG
1911 //\r
1912 break;\r
1913 }\r
1914\r
84f9a9ec 1915 //\r
e9668a60 1916 // Add default value for standard ID by CheckBox Flag\r
84f9a9ec 1917 //\r
e9668a60
LG
1918 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1919 //\r
1920 // Prepare new DefaultValue\r
1921 //\r
ef40f0f6 1922 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1923 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1924 //\r
e9668a60 1925 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1926 //\r
e7fd76d1
ED
1927 DefaultData.Type = DefaultValueFromFlag;\r
1928 DefaultData.Value.b = TRUE;\r
e9668a60 1929 } else {\r
84f9a9ec 1930 //\r
e9668a60 1931 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1932 //\r
e7fd76d1
ED
1933 DefaultData.Type = DefaultValueFromDefault;\r
1934 DefaultData.Value.b = FALSE;\r
84f9a9ec 1935 }\r
e9668a60
LG
1936 //\r
1937 // Add DefaultValue into current BlockData\r
1938 //\r
ef40f0f6 1939 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 1940\r
e9668a60
LG
1941 //\r
1942 // Add default value for Manufacture ID by CheckBox Flag\r
1943 //\r
1944 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1945 //\r
1946 // Prepare new DefaultValue\r
1947 //\r
ef40f0f6 1948 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1949 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1950 //\r
e9668a60 1951 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1952 //\r
e7fd76d1
ED
1953 DefaultData.Type = DefaultValueFromFlag;\r
1954 DefaultData.Value.b = TRUE;\r
e9668a60 1955 } else {\r
84f9a9ec 1956 //\r
e9668a60 1957 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1958 //\r
82e8c138 1959 DefaultData.Type = DefaultValueFromDefault;\r
e7fd76d1 1960 DefaultData.Value.b = FALSE;\r
84f9a9ec 1961 }\r
e9668a60
LG
1962 //\r
1963 // Add DefaultValue into current BlockData\r
1964 //\r
ef40f0f6 1965 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec
LG
1966 break;\r
1967\r
d9bbabfd
ED
1968 case EFI_IFR_DATE_OP:\r
1969 //\r
1970 // offset by question header\r
1971 // width MaxSize * sizeof (CHAR16)\r
1972 // no default value, only block array\r
1973 //\r
1974\r
1975 //\r
1976 // Date question is not in IFR Form. This IFR form is not valid. \r
1977 //\r
22031c4f 1978 if (VarStoreId == 0) {\r
d9bbabfd
ED
1979 Status = EFI_INVALID_PARAMETER;\r
1980 goto Done;\r
1981 }\r
1982 //\r
1983 // Check whether this question is for the requested varstore.\r
1984 //\r
1985 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
22031c4f 1986 if (IfrDate->Question.VarStoreId != VarStoreId) {\r
d9bbabfd
ED
1987 break;\r
1988 }\r
1989\r
d9bbabfd 1990 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
82e8c138
ED
1991 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1992 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
1993 goto Done;\r
1994 }\r
d9bbabfd
ED
1995 break;\r
1996\r
1997 case EFI_IFR_TIME_OP:\r
1998 //\r
1999 // offset by question header\r
2000 // width MaxSize * sizeof (CHAR16)\r
2001 // no default value, only block array\r
2002 //\r
2003\r
2004 //\r
2005 // Time question is not in IFR Form. This IFR form is not valid. \r
2006 //\r
22031c4f 2007 if (VarStoreId == 0) {\r
d9bbabfd
ED
2008 Status = EFI_INVALID_PARAMETER;\r
2009 goto Done;\r
2010 }\r
2011 //\r
2012 // Check whether this question is for the requested varstore.\r
2013 //\r
2014 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
22031c4f 2015 if (IfrTime->Question.VarStoreId != VarStoreId) {\r
d9bbabfd
ED
2016 break;\r
2017 }\r
2018\r
d9bbabfd 2019 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
82e8c138
ED
2020 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2021 if (EFI_ERROR (Status)) {\r
d9bbabfd
ED
2022 goto Done;\r
2023 }\r
d9bbabfd
ED
2024 break;\r
2025\r
84f9a9ec
LG
2026 case EFI_IFR_STRING_OP:\r
2027 //\r
2028 // offset by question header\r
2029 // width MaxSize * sizeof (CHAR16)\r
2030 // no default value, only block array\r
2031 //\r
2032\r
8567300a
LG
2033 //\r
2034 // String question is not in IFR Form. This IFR form is not valid. \r
2035 //\r
22031c4f 2036 if (VarStoreId == 0) {\r
8567300a
LG
2037 Status = EFI_INVALID_PARAMETER;\r
2038 goto Done;\r
2039 }\r
84f9a9ec
LG
2040 //\r
2041 // Check whether this question is for the requested varstore.\r
2042 //\r
2043 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
22031c4f 2044 if (IfrString->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2045 break;\r
2046 }\r
84f9a9ec 2047\r
82e8c138
ED
2048 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
2049 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2050 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
2051 goto Done;\r
2052 }\r
82e8c138 2053\r
84f9a9ec
LG
2054 //\r
2055 // No default value for string.\r
2056 //\r
2057 BlockData = NULL;\r
2058 break;\r
2059\r
2060 case EFI_IFR_PASSWORD_OP:\r
2061 //\r
2062 // offset by question header\r
2063 // width MaxSize * sizeof (CHAR16)\r
2064 // no default value, only block array\r
2065 //\r
2066\r
8567300a
LG
2067 //\r
2068 // Password question is not in IFR Form. This IFR form is not valid. \r
2069 //\r
22031c4f 2070 if (VarStoreId == 0) {\r
8567300a
LG
2071 Status = EFI_INVALID_PARAMETER;\r
2072 goto Done;\r
2073 }\r
84f9a9ec
LG
2074 //\r
2075 // Check whether this question is for the requested varstore.\r
2076 //\r
2077 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
22031c4f 2078 if (IfrPassword->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2079 break;\r
2080 }\r
84f9a9ec 2081\r
82e8c138
ED
2082 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
2083 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2084 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
2085 goto Done;\r
2086 }\r
82e8c138 2087\r
84f9a9ec
LG
2088 //\r
2089 // No default value for string.\r
2090 //\r
2091 BlockData = NULL;\r
2092 break;\r
2093\r
2094 case EFI_IFR_ONE_OF_OPTION_OP:\r
2095 //\r
2096 // No matched block data is ignored.\r
2097 //\r
2098 if (BlockData == NULL || BlockData->Scope == 0) {\r
2099 break;\r
2100 }\r
82e8c138 2101\r
84f9a9ec
LG
2102 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
2103 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2104 //\r
2105 // Get ordered list option data type.\r
2106 //\r
2107 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
2108 VarWidth = 1;\r
2109 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
2110 VarWidth = 2;\r
2111 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
2112 VarWidth = 4;\r
2113 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
2114 VarWidth = 8;\r
2115 } else {\r
2116 //\r
2117 // Invalid ordered list option data type.\r
2118 //\r
2119 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
2120 if (BlockData->Name != NULL) {\r
2121 FreePool (BlockData->Name);\r
2122 }\r
ff28420b 2123 FreePool (BlockData);\r
84f9a9ec
LG
2124 goto Done;\r
2125 }\r
ff28420b 2126\r
84f9a9ec
LG
2127 //\r
2128 // Calculate Ordered list QuestionId width.\r
2129 //\r
2130 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
ff28420b
LG
2131 //\r
2132 // Check whether this question is in requested block array.\r
2133 //\r
70066a82 2134 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
ff28420b
LG
2135 //\r
2136 // This question is not in the requested string. Skip it.\r
2137 //\r
82e8c138
ED
2138 if (BlockData->Name != NULL) {\r
2139 FreePool (BlockData->Name);\r
2140 }\r
ff28420b
LG
2141 FreePool (BlockData);\r
2142 BlockData = NULL;\r
2143 break;\r
2144 }\r
2145 //\r
2146 // Check this var question is in the var storage \r
2147 //\r
82e8c138 2148 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
ff28420b 2149 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
2150 if (BlockData->Name != NULL) {\r
2151 FreePool (BlockData->Name);\r
2152 }\r
ff28420b
LG
2153 FreePool (BlockData);\r
2154 goto Done;\r
2155 }\r
2156 //\r
2157 // Add Block Data into VarStorageData BlockEntry\r
2158 //\r
2159 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
2160 //\r
2161 // No default data for OrderedList.\r
2162 //\r
84f9a9ec
LG
2163 BlockData = NULL;\r
2164 break;\r
2165 }\r
2166\r
ef40f0f6
ED
2167 //\r
2168 // 1. Set default value for OneOf option when flag field has default attribute.\r
2169 //\r
cf4c5a42 2170 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
ef40f0f6 2171 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
cf4c5a42
LG
2172 //\r
2173 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2174 // The first oneof option value will be used as default value when no default value is specified. \r
2175 //\r
2176 FirstOneOfOption = FALSE;\r
ef40f0f6 2177 \r
84f9a9ec
LG
2178 // Prepare new DefaultValue\r
2179 //\r
82e8c138 2180 DefaultData.Type = DefaultValueFromFlag;\r
a7f87053 2181 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2182 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
2183 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2184 InsertDefaultValue (BlockData, &DefaultData);\r
2185 } \r
2186 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
2187 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2188 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 2189 }\r
ef40f0f6 2190 }\r
82e8c138 2191\r
ef40f0f6
ED
2192 //\r
2193 // 2. Set as the default value when this is the first option.\r
2194 // The first oneof option value will be used as default value when no default value is specified. \r
2195 //\r
2196 if (FirstOneOfOption) {\r
2197 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2198 FirstOneOfOption = FALSE;\r
2199 \r
84f9a9ec
LG
2200 //\r
2201 // Prepare new DefaultValue\r
ef40f0f6 2202 // \r
82e8c138 2203 DefaultData.Type = DefaultValueFromDefault;\r
a7f87053 2204 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2205 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2206 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
2207 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2208 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2209 }\r
84f9a9ec
LG
2210 }\r
2211 break;\r
2212\r
2213 case EFI_IFR_DEFAULT_OP:\r
2214 //\r
2215 // Update Current BlockData to the default value.\r
2216 //\r
2217 if (BlockData == NULL || BlockData->Scope == 0) {\r
2218 //\r
82e8c138 2219 // No matched block data is ignored.\r
84f9a9ec
LG
2220 //\r
2221 break;\r
2222 }\r
2223\r
2224 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2225 //\r
2226 // OrderedList Opcode is no default value.\r
2227 //\r
2228 break;\r
2229 }\r
2230 //\r
81b618fe 2231 // Get the DefaultId\r
84f9a9ec
LG
2232 //\r
2233 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
2234 VarDefaultId = IfrDefault->DefaultId;\r
84f9a9ec
LG
2235 //\r
2236 // Prepare new DefaultValue\r
2237 //\r
eb5e7d3e 2238 DefaultData.Type = DefaultValueFromOpcode;\r
ef40f0f6 2239 DefaultData.DefaultId = VarDefaultId;\r
23fe74dc 2240 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
82e8c138 2241\r
ef40f0f6
ED
2242 // If the value field is expression, set the cleaned flag.\r
2243 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
2244 DefaultData.Cleaned = TRUE;\r
84f9a9ec 2245 }\r
84f9a9ec
LG
2246 //\r
2247 // Add DefaultValue into current BlockData\r
2248 //\r
ef40f0f6 2249 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2250\r
ef40f0f6
ED
2251 //\r
2252 // After insert the default value, reset the cleaned value for next \r
2253 // time used. If not set here, need to set the value before everytime \r
2254 // use it.\r
2255 //\r
2256 DefaultData.Cleaned = FALSE;\r
84f9a9ec 2257 break;\r
82e8c138 2258\r
84f9a9ec
LG
2259 case EFI_IFR_END_OP:\r
2260 //\r
8567300a 2261 // End Opcode is for Var question.\r
84f9a9ec 2262 //\r
7248790e
ED
2263 if (BlockData != NULL) {\r
2264 if (BlockData->Scope > 0) {\r
2265 BlockData->Scope--;\r
2266 }\r
2267 if (BlockData->Scope == 0) {\r
2268 BlockData = NULL;\r
2269 }\r
84f9a9ec 2270 }\r
7248790e 2271\r
84f9a9ec 2272 break;\r
82e8c138 2273\r
84f9a9ec 2274 default:\r
7248790e
ED
2275 if (BlockData != NULL) {\r
2276 if (BlockData->Scope > 0) {\r
2277 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
2278 }\r
2279\r
2280 if (BlockData->Scope == 0) {\r
2281 BlockData = NULL;\r
2282 }\r
84f9a9ec
LG
2283 }\r
2284 break;\r
2285 }\r
2286\r
22031c4f
ED
2287 IfrOffset += IfrOpHdr->Length;\r
2288 PackageOffset += IfrOpHdr->Length;\r
84f9a9ec
LG
2289 }\r
2290\r
2291Done:\r
ef40f0f6
ED
2292 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2293 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2294 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
2295 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2296 LinkDefault = LinkDefault->ForwardLink;\r
2297 if (DefaultDataPtr->Cleaned == TRUE) {\r
2298 RemoveEntryList (&DefaultDataPtr->Entry);\r
2299 FreePool (DefaultDataPtr);\r
2300 }\r
2301 }\r
2302 }\r
2303\r
82e8c138 2304 return Status;\r
84f9a9ec
LG
2305}\r
2306\r
2307/**\r
82e8c138 2308 parse the configrequest string, get the elements.\r
84f9a9ec 2309\r
82e8c138
ED
2310 @param ConfigRequest The input configrequest string.\r
2311 @param Progress Return the progress data.\r
2312\r
2313 @retval Block data pointer.\r
2314**/\r
2315IFR_BLOCK_DATA *\r
2316GetBlockElement (\r
2317 IN EFI_STRING ConfigRequest,\r
2318 OUT EFI_STRING *Progress\r
2319 )\r
2320{\r
2321 EFI_STRING StringPtr;\r
2322 IFR_BLOCK_DATA *BlockData;\r
2323 IFR_BLOCK_DATA *RequestBlockArray;\r
2324 EFI_STATUS Status;\r
2325 UINT8 *TmpBuffer;\r
2326 UINT16 Offset;\r
2327 UINT16 Width;\r
2328 LIST_ENTRY *Link;\r
2329 IFR_BLOCK_DATA *NextBlockData;\r
2330 UINTN Length;\r
2331\r
2332 //\r
2333 // Init RequestBlockArray\r
2334 //\r
2335 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2336 if (RequestBlockArray == NULL) {\r
2337 goto Done;\r
2338 }\r
2339 InitializeListHead (&RequestBlockArray->Entry);\r
2340\r
2341 //\r
2342 // Get the request Block array from the request string\r
2343 // Offset and Width\r
2344 //\r
2345\r
2346 //\r
2347 // Parse each <RequestElement> if exists\r
2348 // Only <BlockName> format is supported by this help function.\r
2349 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
2350 //\r
2351 StringPtr = ConfigRequest;\r
2352 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
2353 //\r
2354 // Skip the OFFSET string\r
2355 //\r
2356 *Progress = StringPtr;\r
2357 StringPtr += StrLen (L"&OFFSET=");\r
2358 //\r
2359 // Get Offset\r
2360 //\r
2361 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2362 if (EFI_ERROR (Status)) {\r
2363 goto Done;\r
2364 }\r
2365 Offset = 0;\r
2366 CopyMem (\r
2367 &Offset,\r
2368 TmpBuffer,\r
2369 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2370 );\r
2371 FreePool (TmpBuffer);\r
2372\r
2373 StringPtr += Length;\r
2374 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2375 goto Done;\r
2376 }\r
2377 StringPtr += StrLen (L"&WIDTH=");\r
2378\r
2379 //\r
2380 // Get Width\r
2381 //\r
2382 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2383 if (EFI_ERROR (Status)) {\r
2384 goto Done;\r
2385 }\r
2386 Width = 0;\r
2387 CopyMem (\r
2388 &Width,\r
2389 TmpBuffer,\r
2390 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2391 );\r
2392 FreePool (TmpBuffer);\r
2393\r
2394 StringPtr += Length;\r
2395 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2396 goto Done;\r
2397 }\r
2398 \r
2399 //\r
2400 // Set Block Data\r
2401 //\r
2402 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2403 if (BlockData == NULL) {\r
2404 goto Done;\r
2405 }\r
2406 BlockData->Offset = Offset;\r
2407 BlockData->Width = Width;\r
2408 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2409\r
2410 //\r
2411 // Skip &VALUE string if &VALUE does exists.\r
2412 //\r
2413 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
2414 StringPtr += StrLen (L"&VALUE=");\r
2415\r
2416 //\r
2417 // Get Value\r
2418 //\r
2419 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2420 if (EFI_ERROR (Status)) {\r
2421 goto Done;\r
2422 }\r
2423\r
2424 StringPtr += Length;\r
2425 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2426 goto Done;\r
2427 }\r
2428 }\r
2429 //\r
2430 // If '\0', parsing is finished. \r
2431 //\r
2432 if (*StringPtr == 0) {\r
2433 break;\r
2434 }\r
2435 }\r
2436\r
2437 //\r
2438 // Merge the requested block data.\r
2439 //\r
2440 Link = RequestBlockArray->Entry.ForwardLink;\r
2441 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
2442 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2443 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
2444 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
2445 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
2446 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
2447 }\r
2448 RemoveEntryList (Link->ForwardLink);\r
2449 FreePool (NextBlockData);\r
2450 continue;\r
2451 }\r
2452 Link = Link->ForwardLink;\r
2453 }\r
2454\r
2455 return RequestBlockArray;\r
2456\r
2457Done:\r
2458 if (RequestBlockArray != NULL) {\r
2459 //\r
2460 // Free Link Array RequestBlockArray\r
2461 //\r
2462 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2463 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2464 RemoveEntryList (&BlockData->Entry);\r
2465 FreePool (BlockData);\r
2466 }\r
2467\r
2468 FreePool (RequestBlockArray);\r
2469 }\r
2470\r
2471 return NULL;\r
2472}\r
2473\r
2474/**\r
2475 parse the configrequest string, get the elements.\r
2476\r
2477 @param ConfigRequest The input config request string.\r
2478 @param Progress Return the progress data.\r
2479\r
2480 @retval return data block array.\r
2481**/\r
2482IFR_BLOCK_DATA *\r
2483GetNameElement (\r
2484 IN EFI_STRING ConfigRequest,\r
2485 OUT EFI_STRING *Progress\r
2486 )\r
2487{\r
2488 EFI_STRING StringPtr;\r
2489 EFI_STRING NextTag;\r
2490 IFR_BLOCK_DATA *BlockData;\r
2491 IFR_BLOCK_DATA *RequestBlockArray;\r
2492 BOOLEAN HasValue;\r
2493\r
2494 StringPtr = ConfigRequest;\r
2495\r
2496 //\r
2497 // Init RequestBlockArray\r
2498 //\r
2499 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2500 if (RequestBlockArray == NULL) {\r
2501 goto Done;\r
2502 }\r
2503 InitializeListHead (&RequestBlockArray->Entry);\r
2504\r
2505 //\r
2506 // Get the request Block array from the request string\r
2507 //\r
2508\r
2509 //\r
2510 // Parse each <RequestElement> if exists\r
2511 // Only <BlockName> format is supported by this help function.\r
2512 // <BlockName> ::= &'Name***=***\r
2513 //\r
2514 while (StringPtr != NULL && *StringPtr == L'&') {\r
2515\r
2516 *Progress = StringPtr;\r
2517 //\r
2518 // Skip the L"&" string\r
2519 //\r
2520 StringPtr += 1;\r
2521\r
2522 HasValue = FALSE;\r
2523 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
2524 *NextTag = L'\0';\r
2525 HasValue = TRUE;\r
2526 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
2527 *NextTag = L'\0';\r
2528 }\r
2529\r
2530 //\r
2531 // Set Block Data\r
2532 //\r
2533 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2534 if (BlockData == NULL) {\r
2535 goto Done;\r
2536 }\r
2537\r
2538 //\r
2539 // Get Name\r
2540 //\r
2541 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
2542 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2543\r
2544 if (HasValue) {\r
2545 //\r
2546 // If has value, skip the value.\r
2547 // \r
2548 StringPtr = NextTag + 1;\r
2549 *NextTag = L'=';\r
2550 StringPtr = StrStr (StringPtr, L"&");\r
2551 } else if (NextTag != NULL) {\r
2552 //\r
2553 // restore the '&' text.\r
2554 //\r
2555 StringPtr = NextTag;\r
2556 *NextTag = L'&';\r
2557 }\r
2558 }\r
2559\r
2560 return RequestBlockArray;\r
2561\r
2562Done:\r
2563 if (RequestBlockArray != NULL) {\r
2564 //\r
2565 // Free Link Array RequestBlockArray\r
2566 //\r
2567 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2568 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2569 RemoveEntryList (&BlockData->Entry);\r
2570 if (BlockData->Name != NULL) {\r
2571 FreePool (BlockData->Name);\r
2572 }\r
2573 FreePool (BlockData);\r
2574 }\r
2575\r
2576 FreePool (RequestBlockArray);\r
2577 }\r
2578\r
2579 return NULL;\r
2580}\r
2581\r
2582/**\r
2583 Generate ConfigRequest string base on the varstore info.\r
2584\r
2585 @param ConfigHdr The config header for this varstore.\r
2586 @param VarStorageData The varstore info.\r
2587 @param Status Return Status.\r
2588 @param ConfigRequest The ConfigRequest info may be return.\r
2589\r
2590 @retval TRUE Need to continue\r
2591 @retval Others NO need to continue or error occur.\r
2592**/\r
2593BOOLEAN\r
2594GenerateConfigRequest (\r
2595 IN CHAR16 *ConfigHdr,\r
2596 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2597 OUT EFI_STATUS *Status,\r
2598 IN OUT EFI_STRING *ConfigRequest\r
2599 )\r
2600{\r
2601 BOOLEAN DataExist;\r
2602 UINTN Length;\r
2603 LIST_ENTRY *Link;\r
2604 CHAR16 *FullConfigRequest;\r
2605 CHAR16 *StringPtr;\r
2606 IFR_BLOCK_DATA *BlockData;\r
2607\r
2608 //\r
2609 // Append VarStorageData BlockEntry into *Request string\r
2610 // Now support only one varstore in a form package.\r
2611 //\r
2612 \r
2613 //\r
2614 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
2615 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
2616 //\r
2617 \r
2618 //\r
2619 // Compute the length of the entire request starting with <ConfigHdr> and a \r
2620 // Null-terminator\r
2621 //\r
2622 DataExist = FALSE;\r
2623 Length = StrLen (ConfigHdr) + 1;\r
2624\r
2625 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2626 DataExist = TRUE;\r
2627 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2628 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2629 //\r
2630 // Add <BlockName> length for each Name\r
2631 //\r
2632 // <BlockName> ::= &Name1&Name2&... \r
2633 // |1| StrLen(Name1)\r
2634 //\r
2635 Length = Length + (1 + StrLen (BlockData->Name));\r
2636 } else {\r
2637 //\r
2638 // Add <BlockName> length for each Offset/Width pair\r
2639 //\r
2640 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
2641 // | 8 | 4 | 7 | 4 |\r
2642 //\r
2643 Length = Length + (8 + 4 + 7 + 4);\r
2644 }\r
2645 }\r
2646 //\r
2647 // No any request block data is found. The request string can't be constructed.\r
2648 //\r
2649 if (!DataExist) {\r
2650 *Status = EFI_SUCCESS;\r
2651 return FALSE;\r
2652 }\r
2653\r
2654 //\r
2655 // Allocate buffer for the entire <ConfigRequest>\r
2656 //\r
2657 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
2658 if (FullConfigRequest == NULL) {\r
2659 *Status = EFI_OUT_OF_RESOURCES;\r
2660 return FALSE;\r
2661 }\r
2662 StringPtr = FullConfigRequest;\r
2663\r
2664 //\r
2665 // Start with <ConfigHdr>\r
2666 //\r
2667 StrCpy (StringPtr, ConfigHdr);\r
2668 StringPtr += StrLen (StringPtr);\r
2669\r
2670 //\r
2671 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
2672 //\r
2673 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2674 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2675 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2676 //\r
2677 // Append &Name1\0\r
2678 //\r
2679 UnicodeSPrint (\r
2680 StringPtr,\r
2681 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
2682 L"&%s",\r
2683 BlockData->Name\r
2684 );\r
2685 } else {\r
2686 //\r
2687 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
2688 //\r
2689 UnicodeSPrint (\r
2690 StringPtr, \r
2691 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
2692 L"&OFFSET=%04X&WIDTH=%04X", \r
2693 BlockData->Offset, \r
2694 BlockData->Width\r
2695 );\r
2696 }\r
2697 StringPtr += StrLen (StringPtr);\r
2698 }\r
2699 //\r
2700 // Set to the got full request string.\r
2701 //\r
2702 HiiToLower (FullConfigRequest);\r
2703\r
2704 if (*ConfigRequest != NULL) {\r
2705 FreePool (*ConfigRequest);\r
2706 }\r
2707 *ConfigRequest = FullConfigRequest;\r
2708\r
2709 return TRUE;\r
2710}\r
2711\r
2712/**\r
2713 Generate ConfigRequest Header base on the varstore info.\r
2714\r
2715 @param VarStorageData The varstore info.\r
2716 @param DevicePath Device path for this varstore.\r
2717 @param ConfigHdr The config header for this varstore.\r
2718\r
2719 @retval EFI_SUCCESS Generate the header success.\r
2720 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
2721**/\r
2722EFI_STATUS\r
2723GenerateHdr (\r
2724 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2725 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2726 OUT EFI_STRING *ConfigHdr\r
2727 )\r
2728{\r
2729 EFI_STRING GuidStr;\r
2730 EFI_STRING NameStr;\r
2731 EFI_STRING PathStr;\r
2732 UINTN Length;\r
2733 EFI_STATUS Status;\r
2734\r
2735 Status = EFI_SUCCESS;\r
2736 NameStr = NULL;\r
2737 GuidStr = NULL;\r
2738 PathStr = NULL;\r
2739\r
2740 //\r
2741 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
2742 //\r
2743 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
2744 if (VarStorageData->Name != NULL) {\r
2745 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
2746 } else {\r
2747 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
2748 }\r
2749 GenerateSubStr (\r
2750 L"PATH=",\r
2751 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2752 (VOID *) DevicePath,\r
2753 1,\r
2754 &PathStr\r
2755 );\r
2756 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
2757 if (VarStorageData->Name == NULL) {\r
2758 Length += 1;\r
2759 }\r
2760\r
2761 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
2762 if (*ConfigHdr == NULL) {\r
2763 Status = EFI_OUT_OF_RESOURCES;\r
2764 goto Done;\r
2765 }\r
2766 StrCpy (*ConfigHdr, GuidStr);\r
2767 StrCat (*ConfigHdr, NameStr);\r
2768 if (VarStorageData->Name == NULL) {\r
2769 StrCat (*ConfigHdr, L"&");\r
2770 }\r
2771 StrCat (*ConfigHdr, PathStr);\r
2772\r
2773 //\r
2774 // Remove the last character L'&'\r
2775 //\r
2776 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
2777\r
2778Done:\r
2779 if (GuidStr != NULL) {\r
2780 FreePool (GuidStr);\r
2781 }\r
2782\r
2783 if (NameStr != NULL) {\r
2784 FreePool (NameStr);\r
2785 }\r
2786\r
2787 if (PathStr != NULL) {\r
2788 FreePool (PathStr);\r
2789 }\r
2790\r
2791 return Status;\r
2792}\r
2793\r
2794/**\r
2795 Get Data buffer size based on data type.\r
2796\r
2797 @param ValueType The input data type.\r
2798\r
2799 @retval The data buffer size for the input type.\r
2800**/\r
2801UINT16\r
2802GetStorageWidth (\r
2803 IN UINT8 ValueType\r
2804 )\r
2805{\r
2806 UINT16 StorageWidth;\r
2807\r
2808 switch (ValueType) {\r
2809 case EFI_IFR_NUMERIC_SIZE_1:\r
2810 case EFI_IFR_TYPE_BOOLEAN:\r
2811 StorageWidth = (UINT16) sizeof (UINT8);\r
2812 break;\r
2813\r
2814 case EFI_IFR_NUMERIC_SIZE_2:\r
2815 StorageWidth = (UINT16) sizeof (UINT16);\r
2816 break;\r
2817\r
2818 case EFI_IFR_NUMERIC_SIZE_4:\r
2819 StorageWidth = (UINT16) sizeof (UINT32);\r
2820 break;\r
2821\r
2822 case EFI_IFR_NUMERIC_SIZE_8:\r
2823 StorageWidth = (UINT16) sizeof (UINT64);\r
2824 break;\r
2825\r
2826 case EFI_IFR_TYPE_TIME:\r
2827 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
2828 break;\r
2829\r
2830 case EFI_IFR_TYPE_DATE:\r
2831 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
2832 break;\r
2833\r
2834 default:\r
2835 StorageWidth = 0;\r
2836 break;\r
2837 }\r
2838\r
2839 return StorageWidth;\r
2840}\r
2841\r
2842/**\r
2843 Generate ConfigAltResp string base on the varstore info.\r
2844\r
2845 @param ConfigHdr The config header for this varstore.\r
2846 @param VarStorageData The varstore info.\r
2847 @param DefaultIdArray The Default id array.\r
2848 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
2849\r
2850 @retval TRUE Need to continue\r
2851 @retval Others NO need to continue or error occur.\r
2852**/\r
2853EFI_STATUS\r
2854GenerateAltConfigResp (\r
2855 IN CHAR16 *ConfigHdr,\r
2856 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2857 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
2858 IN OUT EFI_STRING *DefaultAltCfgResp\r
2859 )\r
2860{\r
2861 BOOLEAN DataExist;\r
2862 UINTN Length;\r
2863 LIST_ENTRY *Link;\r
2864 LIST_ENTRY *LinkData;\r
2865 LIST_ENTRY *LinkDefault;\r
2866 LIST_ENTRY *ListEntry;\r
2867 CHAR16 *StringPtr;\r
2868 IFR_BLOCK_DATA *BlockData;\r
2869 IFR_DEFAULT_DATA *DefaultId;\r
2870 IFR_DEFAULT_DATA *DefaultValueData;\r
2871 UINTN Width;\r
2872 UINT8 *TmpBuffer;\r
2873\r
2874 BlockData = NULL;\r
2875 DataExist = FALSE;\r
2876\r
2877 //\r
2878 // Add length for <ConfigHdr> + '\0'\r
2879 //\r
2880 Length = StrLen (ConfigHdr) + 1;\r
2881\r
2882 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2883 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2884 //\r
2885 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2886 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2887 //\r
2888 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2889 \r
2890 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2891 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2892 ListEntry = &BlockData->DefaultValueEntry;\r
2893 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2894 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2895 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2896 continue;\r
2897 }\r
2898 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2899 //\r
2900 // Add length for "&Name1=zzzzzzzzzzzz"\r
2901 // |1|Name|1|Value|\r
2902 //\r
2903 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
2904 } else {\r
2905 //\r
2906 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2907 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2908 //\r
2909 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2910 }\r
2911 DataExist = TRUE;\r
2912 }\r
2913 }\r
2914 }\r
2915 \r
2916 //\r
2917 // No default value is found. The default string doesn't exist.\r
2918 //\r
2919 if (!DataExist) {\r
2920 return EFI_SUCCESS;\r
2921 }\r
2922\r
2923 //\r
2924 // Allocate buffer for the entire <DefaultAltCfgResp>\r
2925 //\r
2926 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2927 if (*DefaultAltCfgResp == NULL) {\r
2928 return EFI_OUT_OF_RESOURCES;\r
2929 }\r
2930 StringPtr = *DefaultAltCfgResp;\r
2931\r
2932 //\r
2933 // Start with <ConfigHdr>\r
2934 //\r
2935 StrCpy (StringPtr, ConfigHdr);\r
2936 StringPtr += StrLen (StringPtr);\r
2937\r
2938 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2939 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2940 //\r
2941 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2942 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2943 //\r
2944 UnicodeSPrint (\r
2945 StringPtr, \r
2946 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2947 L"&%s&ALTCFG=%04X", \r
2948 ConfigHdr, \r
2949 DefaultId->DefaultId\r
2950 );\r
2951 StringPtr += StrLen (StringPtr);\r
2952\r
2953 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2954 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2955 ListEntry = &BlockData->DefaultValueEntry;\r
2956 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2957 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2958 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2959 continue;\r
2960 }\r
2961 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2962 UnicodeSPrint (\r
2963 StringPtr, \r
2964 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
2965 L"&%s=", \r
2966 BlockData->Name\r
2967 );\r
2968 StringPtr += StrLen (StringPtr);\r
2969 } else {\r
2970 //\r
2971 // Add <BlockConfig>\r
2972 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2973 //\r
2974 UnicodeSPrint (\r
2975 StringPtr, \r
2976 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2977 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2978 BlockData->Offset, \r
2979 BlockData->Width\r
2980 );\r
2981 StringPtr += StrLen (StringPtr);\r
2982 }\r
2983 Width = BlockData->Width;\r
2984 //\r
2985 // Convert Value to a hex string in "%x" format\r
2986 // NOTE: This is in the opposite byte that GUID and PATH use\r
2987 //\r
2988 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2989 for (; Width > 0; Width--) {\r
2990 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2991 }\r
2992 }\r
2993 }\r
2994 }\r
2995\r
2996 HiiToLower (*DefaultAltCfgResp);\r
2997\r
2998 return EFI_SUCCESS;\r
2999}\r
3000\r
3001/**\r
3002 This function gets the full request string and full default value string by \r
3003 parsing IFR data in HII form packages. \r
3004 \r
3005 When Request points to NULL string, the request string and default value string \r
3006 for each varstore in form package will return. \r
3007\r
3008 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
3009 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
3010 @param Request Pointer to a null-terminated Unicode string in\r
3011 <ConfigRequest> format. When it doesn't contain\r
3012 any RequestElement, it will be updated to return \r
3013 the full RequestElement retrieved from IFR data.\r
3014 If it points to NULL, the request string for the first\r
3015 varstore in form package will be merged into a\r
3016 <MultiConfigRequest> format string and return. \r
3017 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
3018 <ConfigAltResp> format. When the pointer is to NULL,\r
3019 the full default value string retrieved from IFR data\r
3020 will return. When the pinter is to a string, the\r
3021 full default value string retrieved from IFR data\r
3022 will be merged into the input string and return.\r
3023 When Request points to NULL, the default value string \r
3024 for each varstore in form package will be merged into \r
3025 a <MultiConfigAltResp> format string and return.\r
3026 @param PointerProgress Optional parameter, it can be be NULL. \r
3027 When it is not NULL, if Request is NULL, it returns NULL. \r
3028 On return, points to a character in the Request\r
3029 string. Points to the string's null terminator if\r
3030 request was successful. Points to the most recent\r
3031 & before the first failing name / value pair (or\r
ae79d2f9
LG
3032 the beginning of the string if the failure is in\r
3033 the first name / value pair) if the request was\r
3034 not successful.\r
84f9a9ec
LG
3035 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3036 And AltCfgResp contains all default value string.\r
3037 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3038 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
3039 can't be found in Form package.\r
3040 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 3041 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
3042\r
3043**/\r
3044EFI_STATUS\r
3045EFIAPI\r
3046GetFullStringFromHiiFormPackages (\r
8567300a 3047 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
3048 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3049 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
3050 IN OUT EFI_STRING *AltCfgResp,\r
3051 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
3052 )\r
3053{\r
3054 EFI_STATUS Status;\r
8567300a
LG
3055 UINT8 *HiiFormPackage;\r
3056 UINTN PackageSize;\r
84f9a9ec
LG
3057 IFR_BLOCK_DATA *RequestBlockArray;\r
3058 IFR_BLOCK_DATA *BlockData;\r
84f9a9ec
LG
3059 IFR_DEFAULT_DATA *DefaultValueData;\r
3060 IFR_DEFAULT_DATA *DefaultId;\r
3061 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
3062 IFR_VARSTORAGE_DATA *VarStorageData;\r
3063 EFI_STRING DefaultAltCfgResp;\r
40ae09a2
ED
3064 EFI_STRING ConfigHdr;\r
3065 EFI_STRING StringPtr;\r
3066 EFI_STRING Progress;\r
40ae09a2
ED
3067\r
3068 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
3069 return EFI_INVALID_PARAMETER;\r
ae79d2f9
LG
3070 }\r
3071\r
84f9a9ec
LG
3072 //\r
3073 // Initialize the local variables.\r
3074 //\r
3075 RequestBlockArray = NULL;\r
8567300a 3076 DefaultIdArray = NULL;\r
84f9a9ec
LG
3077 VarStorageData = NULL;\r
3078 DefaultAltCfgResp = NULL;\r
40ae09a2
ED
3079 ConfigHdr = NULL;\r
3080 HiiFormPackage = NULL;\r
3081 PackageSize = 0;\r
40ae09a2
ED
3082 Progress = *Request;\r
3083\r
3084 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
84f9a9ec 3085 if (EFI_ERROR (Status)) {\r
cce6230f 3086 return Status;\r
84f9a9ec
LG
3087 }\r
3088\r
3089 //\r
8567300a 3090 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
3091 //\r
3092 StringPtr = NULL;\r
3093 if (*Request != NULL) {\r
ae79d2f9
LG
3094 StringPtr = *Request;\r
3095 //\r
3096 // Jump <ConfigHdr>\r
3097 //\r
3098 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3099 Status = EFI_INVALID_PARAMETER;\r
3100 goto Done;\r
3101 }\r
3102 StringPtr += StrLen (L"GUID=");\r
3103 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3104 StringPtr++;\r
3105 }\r
3106 if (*StringPtr == L'\0') {\r
3107 Status = EFI_INVALID_PARAMETER;\r
3108 goto Done;\r
3109 }\r
3110 StringPtr += StrLen (L"&NAME=");\r
82e8c138
ED
3111 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3112 StringPtr++;\r
6e3f5b2a 3113 }\r
82e8c138
ED
3114 if (*StringPtr == L'\0') {\r
3115 Status = EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
3116 goto Done;\r
3117 }\r
82e8c138
ED
3118 StringPtr += StrLen (L"&PATH=");\r
3119 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3120 StringPtr ++;\r
3121 }\r
84f9a9ec 3122\r
82e8c138 3123 if (*StringPtr == L'\0') {\r
84f9a9ec 3124 //\r
82e8c138 3125 // No request block is found.\r
84f9a9ec 3126 //\r
82e8c138 3127 StringPtr = NULL;\r
84f9a9ec 3128 }\r
84f9a9ec 3129 }\r
82e8c138 3130\r
93e3992d 3131 //\r
82e8c138 3132 // If StringPtr != NULL, get the request elements.\r
93e3992d 3133 //\r
82e8c138
ED
3134 if (StringPtr != NULL) {\r
3135 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
3136 RequestBlockArray = GetBlockElement(StringPtr, &Progress);\r
3137 } else {\r
3138 RequestBlockArray = GetNameElement(StringPtr, &Progress);\r
3139 }\r
3140\r
3141 if (RequestBlockArray == NULL) {\r
3142 Status = EFI_INVALID_PARAMETER;\r
3143 goto Done;\r
84f9a9ec 3144 }\r
93e3992d 3145 }\r
82e8c138 3146\r
6e3f5b2a 3147 //\r
82e8c138 3148 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
6e3f5b2a 3149 //\r
82e8c138
ED
3150 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
3151 if (DefaultIdArray == NULL) {\r
3152 Status = EFI_OUT_OF_RESOURCES;\r
6e3f5b2a
LG
3153 goto Done;\r
3154 }\r
82e8c138 3155 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 3156\r
93e3992d 3157 //\r
82e8c138 3158 // Initialize VarStorageData to store the var store Block and Default value information.\r
93e3992d 3159 //\r
82e8c138
ED
3160 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
3161 if (VarStorageData == NULL) {\r
6e3f5b2a 3162 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
3163 goto Done;\r
3164 }\r
82e8c138
ED
3165 InitializeListHead (&VarStorageData->Entry);\r
3166 InitializeListHead (&VarStorageData->BlockEntry);\r
93e3992d 3167\r
84f9a9ec 3168 //\r
82e8c138 3169 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 3170 //\r
93e3992d 3171\r
82e8c138
ED
3172 //\r
3173 // Parse the opcode in form pacakge to get the default setting.\r
3174 //\r
3175 Status = ParseIfrData (DataBaseRecord->Handle,\r
3176 HiiFormPackage,\r
3177 (UINT32) PackageSize,\r
3178 *Request,\r
3179 RequestBlockArray,\r
3180 VarStorageData,\r
3181 DefaultIdArray);\r
3182 if (EFI_ERROR (Status)) {\r
3183 goto Done;\r
3184 }\r
84f9a9ec 3185\r
82e8c138
ED
3186 //\r
3187 // No requested varstore in IFR data and directly return\r
3188 //\r
22031c4f 3189 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {\r
82e8c138
ED
3190 Status = EFI_SUCCESS;\r
3191 goto Done;\r
3192 }\r
3193\r
3194 //\r
3195 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
3196 //\r
3197 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
3198 if (EFI_ERROR (Status)) {\r
3199 goto Done;\r
3200 }\r
3201\r
3202 if (RequestBlockArray == NULL) {\r
3203 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {\r
3204 goto Done;\r
84f9a9ec 3205 }\r
93e3992d 3206 }\r
82e8c138
ED
3207\r
3208 //\r
3209 // 4. Construct Default Value string in AltResp according to request element.\r
3210 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
3211 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
3212 //\r
3213 Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
3214 if (EFI_ERROR (Status)) {\r
3215 goto Done;\r
3216 }\r
93e3992d 3217\r
84f9a9ec
LG
3218 //\r
3219 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
3220 //\r
6e3f5b2a 3221 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
3222 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
3223 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
3224 } else if (*AltCfgResp == NULL) {\r
3225 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 3226 }\r
93e3992d 3227\r
84f9a9ec
LG
3228Done:\r
3229 if (RequestBlockArray != NULL) {\r
3230 //\r
3231 // Free Link Array RequestBlockArray\r
3232 //\r
3233 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3234 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3235 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3236 if (BlockData->Name != NULL) {\r
3237 FreePool (BlockData->Name);\r
3238 }\r
84f9a9ec
LG
3239 FreePool (BlockData);\r
3240 }\r
3241\r
3242 FreePool (RequestBlockArray);\r
93e3992d 3243 }\r
82e8c138 3244\r
84f9a9ec
LG
3245 if (VarStorageData != NULL) {\r
3246 //\r
3247 // Free link array VarStorageData\r
3248 //\r
3249 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
3250 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3251 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
3252 if (BlockData->Name != NULL) {\r
3253 FreePool (BlockData->Name);\r
3254 }\r
84f9a9ec
LG
3255 //\r
3256 // Free default value link array\r
3257 //\r
3258 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
3259 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3260 RemoveEntryList (&DefaultValueData->Entry);\r
3261 FreePool (DefaultValueData);\r
3262 }\r
3263 FreePool (BlockData);\r
63d55bb9 3264 }\r
84f9a9ec 3265 FreePool (VarStorageData);\r
93e3992d 3266 }\r
3267\r
84f9a9ec
LG
3268 if (DefaultIdArray != NULL) {\r
3269 //\r
3270 // Free DefaultId Array\r
3271 //\r
3272 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
3273 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3274 RemoveEntryList (&DefaultId->Entry);\r
3275 FreePool (DefaultId);\r
3276 }\r
3277 FreePool (DefaultIdArray);\r
3278 }\r
82e8c138 3279\r
84f9a9ec
LG
3280 //\r
3281 // Free the allocated string \r
3282 //\r
84f9a9ec
LG
3283 if (ConfigHdr != NULL) {\r
3284 FreePool (ConfigHdr);\r
3285 }\r
93e3992d 3286\r
84f9a9ec
LG
3287 //\r
3288 // Free Pacakge data\r
3289 //\r
8567300a
LG
3290 if (HiiFormPackage != NULL) {\r
3291 FreePool (HiiFormPackage);\r
676df92c 3292 }\r
63d55bb9 3293\r
ae79d2f9
LG
3294 if (PointerProgress != NULL) {\r
3295 if (*Request == NULL) {\r
3296 *PointerProgress = NULL;\r
3297 } else if (EFI_ERROR (Status)) {\r
82e8c138 3298 *PointerProgress = *Request;\r
ae79d2f9
LG
3299 } else {\r
3300 *PointerProgress = *Request + StrLen (*Request);\r
3301 }\r
3302 }\r
3303\r
93e3992d 3304 return Status;\r
3305}\r
3306\r
cce6230f
ED
3307/**\r
3308 This function gets the full request resp string by \r
3309 parsing IFR data in HII form packages.\r
3310\r
3311 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3312 instance.\r
3313 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3314 varstore data structure. \r
3315 @param Request Pointer to a null-terminated Unicode string in\r
3316 <ConfigRequest> format.\r
3317 @param RequestResp Pointer to a null-terminated Unicode string in\r
3318 <ConfigResp> format.\r
3319 @param AccessProgress On return, points to a character in the Request\r
3320 string. Points to the string's null terminator if\r
3321 request was successful. Points to the most recent\r
3322 & before the first failing name / value pair (or\r
3323 the beginning of the string if the failure is in\r
3324 the first name / value pair) if the request was\r
3325 not successful.\r
3326\r
3327 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3328 And AltCfgResp contains all default value string.\r
3329 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3330 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3331\r
3332**/\r
3333EFI_STATUS\r
3334GetConfigRespFromEfiVarStore (\r
3335 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3336 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3337 IN EFI_STRING Request,\r
3338 OUT EFI_STRING *RequestResp,\r
3339 OUT EFI_STRING *AccessProgress\r
3340 )\r
3341{\r
3342 EFI_STATUS Status;\r
3343 EFI_STRING VarStoreName;\r
3344 UINT8 *VarStore;\r
3345 UINTN BufferSize;\r
3346\r
7248790e
ED
3347 Status = EFI_SUCCESS;\r
3348 BufferSize = 0;\r
3349 VarStore = NULL;\r
3350 VarStoreName = NULL;\r
3351 *AccessProgress = Request;\r
cce6230f
ED
3352 \r
3353 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3354 if (VarStoreName == NULL) {\r
3355 Status = EFI_OUT_OF_RESOURCES;\r
3356 goto Done;\r
3357 }\r
3358 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3359 \r
3360 \r
3361 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3362 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3363 goto Done;\r
3364 }\r
3365\r
3366 VarStore = AllocateZeroPool (BufferSize);\r
3367 ASSERT (VarStore != NULL);\r
3368 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3369 if (EFI_ERROR (Status)) {\r
3370 goto Done;\r
3371 }\r
3372\r
3373 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
3374 if (EFI_ERROR (Status)) {\r
3375 goto Done;\r
3376 }\r
3377\r
3378Done:\r
3379 if (VarStoreName != NULL) {\r
3380 FreePool (VarStoreName);\r
3381 }\r
3382\r
3383 if (VarStore != NULL) {\r
3384 FreePool (VarStore);\r
3385 }\r
3386\r
3387 return Status;\r
3388}\r
3389\r
3390\r
3391/**\r
3392 This function route the full request resp string for efi varstore. \r
3393\r
3394 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3395 instance.\r
3396 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3397 varstore data structure. \r
3398 @param RequestResp Pointer to a null-terminated Unicode string in\r
3399 <ConfigResp> format.\r
3400 @param Result Pointer to a null-terminated Unicode string in\r
3401 <ConfigResp> format.\r
3402 \r
3403 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3404 And AltCfgResp contains all default value string.\r
3405 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3406 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3407\r
3408**/\r
3409EFI_STATUS\r
3410RouteConfigRespForEfiVarStore (\r
3411 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3412 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3413 IN EFI_STRING RequestResp,\r
3414 OUT EFI_STRING *Result\r
3415 )\r
3416{\r
3417 EFI_STATUS Status;\r
3418 EFI_STRING VarStoreName;\r
f26b6a9c 3419 UINT8 *VarStore;\r
cce6230f
ED
3420 UINTN BufferSize;\r
3421 UINTN BlockSize;\r
3422\r
3423 Status = EFI_SUCCESS;\r
3424 BufferSize = 0;\r
3425 VarStore = NULL;\r
3426 VarStoreName = NULL;\r
3427\r
3428 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3429 if (VarStoreName == NULL) {\r
3430 Status = EFI_OUT_OF_RESOURCES;\r
3431 goto Done;\r
3432 }\r
3433 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3434 \r
3435 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3436 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3437 goto Done;\r
3438 }\r
3439\r
3440 BlockSize = BufferSize;\r
3441 VarStore = AllocateZeroPool (BufferSize);\r
3442 ASSERT (VarStore != NULL);\r
3443 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3444 if (EFI_ERROR (Status)) {\r
3445 goto Done;\r
3446 }\r
3447\r
3448 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
3449 if (EFI_ERROR (Status)) {\r
3450 goto Done;\r
3451 }\r
3452\r
3453 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
3454 if (EFI_ERROR (Status)) {\r
3455 goto Done;\r
3456 }\r
3457\r
3458Done:\r
3459 if (VarStoreName != NULL) {\r
3460 FreePool (VarStoreName);\r
3461 }\r
3462\r
3463 if (VarStore != NULL) {\r
3464 FreePool (VarStore);\r
3465 }\r
3466\r
3467 return Status;\r
3468}\r
3469\r
82e8c138
ED
3470/**\r
3471 Validate the config request elements.\r
3472\r
3473 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3474 without configHdr field.\r
3475\r
3476 @retval CHAR16 * THE first Name/value pair not correct.\r
3477 @retval NULL Success parse the name/value pair\r
3478**/\r
3479CHAR16 *\r
3480OffsetWidthValidate (\r
3481 CHAR16 *ConfigElements\r
3482 )\r
3483{\r
3484 CHAR16 *StringPtr;\r
3485 CHAR16 *RetVal;\r
3486\r
3487 StringPtr = ConfigElements;\r
3488\r
3489 while (1) {\r
3490 RetVal = StringPtr;\r
3491 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3492 return RetVal;\r
3493 }\r
3494\r
3495 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3496 StringPtr++;\r
3497 }\r
3498 if (*StringPtr == L'\0') {\r
3499 return RetVal;\r
3500 }\r
3501\r
3502 StringPtr += StrLen (L"&WIDTH=");\r
3503 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3504 StringPtr ++;\r
3505 }\r
3506\r
3507 if (*StringPtr == L'\0') {\r
3508 return NULL;\r
3509 }\r
3510 }\r
3511}\r
3512\r
3513/**\r
3514 Validate the config request elements.\r
3515\r
3516 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3517 without configHdr field.\r
3518\r
3519 @retval CHAR16 * THE first Name/value pair not correct.\r
3520 @retval NULL Success parse the name/value pair\r
3521\r
3522**/\r
3523CHAR16 *\r
3524NameValueValidate (\r
3525 CHAR16 *ConfigElements\r
3526 )\r
3527{\r
3528 CHAR16 *StringPtr;\r
3529 CHAR16 *RetVal;\r
3530\r
3531 StringPtr = ConfigElements;\r
3532\r
3533 while (1) {\r
3534 RetVal = StringPtr;\r
3535 if (*StringPtr != L'&') {\r
3536 return RetVal;\r
3537 }\r
3538 StringPtr += 1;\r
3539\r
3540 StringPtr = StrStr (StringPtr, L"&");\r
3541 \r
3542 if (StringPtr == NULL) {\r
3543 return NULL;\r
3544 }\r
3545 }\r
3546}\r
3547\r
3548/**\r
3549 Validate the config request string.\r
3550\r
3551 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
3552\r
3553 @retval CHAR16 * THE first element not correct.\r
3554 @retval NULL Success parse the name/value pair\r
3555\r
3556**/\r
3557CHAR16 *\r
3558ConfigRequestValidate (\r
3559 CHAR16 *ConfigRequest\r
3560 )\r
3561{\r
3562 BOOLEAN HasNameField;\r
3563 CHAR16 *StringPtr;\r
3564\r
3565 HasNameField = TRUE;\r
3566 StringPtr = ConfigRequest;\r
3567\r
3568 //\r
3569 // Check <ConfigHdr>\r
3570 //\r
3571 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3572 return ConfigRequest;\r
3573 }\r
3574 StringPtr += StrLen (L"GUID=");\r
3575 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3576 StringPtr++;\r
3577 }\r
3578 if (*StringPtr == L'\0') {\r
3579 return ConfigRequest;\r
3580 }\r
3581 StringPtr += StrLen (L"&NAME=");\r
3582 if (*StringPtr == L'&') {\r
3583 HasNameField = FALSE;\r
3584 }\r
3585 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3586 StringPtr++;\r
3587 }\r
3588 if (*StringPtr == L'\0') {\r
3589 return ConfigRequest;\r
3590 }\r
3591 StringPtr += StrLen (L"&PATH=");\r
3592 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3593 StringPtr ++;\r
3594 }\r
3595\r
3596 if (*StringPtr == L'\0') {\r
3597 return NULL;\r
3598 }\r
3599\r
3600 if (HasNameField) {\r
3601 //\r
3602 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
3603 //\r
3604 return OffsetWidthValidate(StringPtr);\r
3605 } else {\r
3606 //\r
3607 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
3608 //\r
3609 return NameValueValidate(StringPtr);\r
3610 }\r
3611}\r
3612\r
93e3992d 3613/**\r
3614 This function allows a caller to extract the current configuration\r
3615 for one or more named elements from one or more drivers.\r
3616\r
3617 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3618 instance.\r
3619 @param Request A null-terminated Unicode string in\r
3620 <MultiConfigRequest> format.\r
3621 @param Progress On return, points to a character in the Request\r
3622 string. Points to the string's null terminator if\r
3623 request was successful. Points to the most recent\r
3624 & before the first failing name / value pair (or\r
3625 the beginning of the string if the failure is in\r
3626 the first name / value pair) if the request was\r
3627 not successful.\r
3628 @param Results Null-terminated Unicode string in\r
3629 <MultiConfigAltResp> format which has all values\r
3630 filled in for the names in the Request string.\r
3631 String to be allocated by the called function.\r
3632\r
3633 @retval EFI_SUCCESS The Results string is filled with the values\r
3634 corresponding to all requested names.\r
3635 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3636 results that must be stored awaiting possible\r
3637 future protocols.\r
3638 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
3639 Progress set to the "G" in "GUID" of the routing\r
3640 header that doesn't match. Note: There is no\r
3641 requirement that all routing data be validated\r
3642 before any configuration extraction.\r
3643 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
3644 parameter would result in this type of error. The\r
3645 Progress parameter is set to NULL.\r
3646 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
3647 before the error or the beginning of the string.\r
46c3efbb
ED
3648 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII\r
3649 Configuration Access Protocol returned \r
3650 EFI_INVALID_PARAMETER. Progress set to most recent\r
3651 & before the error or the beginning of the string.\r
93e3992d 3652\r
3653**/\r
3654EFI_STATUS\r
3655EFIAPI\r
3656HiiConfigRoutingExtractConfig (\r
3657 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3658 IN CONST EFI_STRING Request,\r
3659 OUT EFI_STRING *Progress,\r
3660 OUT EFI_STRING *Results\r
3661 )\r
3662{\r
84f9a9ec 3663 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3664 EFI_STRING StringPtr;\r
3665 EFI_STRING ConfigRequest;\r
3666 UINTN Length;\r
3667 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 3668 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 3669 EFI_STATUS Status;\r
84f9a9ec
LG
3670 LIST_ENTRY *Link;\r
3671 HII_DATABASE_RECORD *Database;\r
3672 UINT8 *DevicePathPkg;\r
3673 UINT8 *CurrentDevicePath;\r
93e3992d 3674 EFI_HANDLE DriverHandle;\r
84f9a9ec 3675 EFI_HII_HANDLE HiiHandle;\r
93e3992d 3676 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3677 EFI_STRING AccessProgress;\r
3678 EFI_STRING AccessResults;\r
84f9a9ec 3679 EFI_STRING DefaultResults;\r
8d00a0f1 3680 BOOLEAN FirstElement;\r
6e3f5b2a 3681 BOOLEAN IfrDataParsedFlag;\r
cce6230f 3682 BOOLEAN IsEfiVarStore;\r
82e8c138
ED
3683 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
3684 EFI_STRING ErrorPtr;\r
7248790e 3685 UINTN DevicePathSize;\r
93e3992d 3686\r
3687 if (This == NULL || Progress == NULL || Results == NULL) {\r
3688 return EFI_INVALID_PARAMETER;\r
3689 }\r
3690\r
3691 if (Request == NULL) {\r
3692 *Progress = NULL;\r
3693 return EFI_INVALID_PARAMETER;\r
3694 }\r
3695\r
84f9a9ec 3696 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 3697 StringPtr = Request;\r
3698 *Progress = StringPtr;\r
84f9a9ec
LG
3699 DefaultResults = NULL;\r
3700 ConfigRequest = NULL;\r
3701 Status = EFI_SUCCESS;\r
3702 AccessResults = NULL;\r
cce6230f 3703 AccessProgress = NULL;\r
84f9a9ec 3704 DevicePath = NULL;\r
6e3f5b2a 3705 IfrDataParsedFlag = FALSE;\r
cce6230f
ED
3706 IsEfiVarStore = FALSE;\r
3707 EfiVarStoreInfo = NULL;\r
93e3992d 3708\r
3709 //\r
3710 // The first element of <MultiConfigRequest> should be\r
3711 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
3712 //\r
3713 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3714 return EFI_INVALID_PARAMETER;\r
3715 }\r
3716\r
8d00a0f1 3717 FirstElement = TRUE;\r
3718\r
93e3992d 3719 //\r
3720 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3721 // Results if this fix length is insufficient.\r
3722 //\r
3723 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3724 if (*Results == NULL) {\r
3725 return EFI_OUT_OF_RESOURCES;\r
3726 }\r
3727\r
3728 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
3729 //\r
3730 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
3731 // or most recent & before the error.\r
3732 //\r
3733 if (StringPtr == Request) {\r
3734 *Progress = StringPtr;\r
3735 } else {\r
3736 *Progress = StringPtr - 1;\r
3737 }\r
3738\r
3739 //\r
3740 // Process each <ConfigRequest> of <MultiConfigRequest>\r
3741 //\r
3742 Length = CalculateConfigStringLen (StringPtr);\r
3743 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
3744 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
3745 Status = EFI_OUT_OF_RESOURCES;\r
3746 goto Done;\r
93e3992d 3747 }\r
3748 *(ConfigRequest + Length) = 0;\r
3749\r
3750 //\r
3751 // Get the UEFI device path\r
3752 //\r
3753 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
3754 if (EFI_ERROR (Status)) {\r
84f9a9ec 3755 goto Done;\r
93e3992d 3756 }\r
3757\r
3758 //\r
84f9a9ec
LG
3759 // Find driver which matches the routing data.\r
3760 //\r
3761 DriverHandle = NULL;\r
3762 HiiHandle = NULL;\r
8567300a 3763 Database = NULL;\r
84f9a9ec
LG
3764 for (Link = Private->DatabaseList.ForwardLink;\r
3765 Link != &Private->DatabaseList;\r
3766 Link = Link->ForwardLink\r
3767 ) {\r
3768 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
3769 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3770 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
7248790e 3771 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
8aaab674 3772 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {\r
84f9a9ec
LG
3773 DriverHandle = Database->DriverHandle;\r
3774 HiiHandle = Database->Handle;\r
3775 break;\r
3776 }\r
3777 }\r
3778 }\r
3779 \r
3780 //\r
3781 // Try to find driver handle by device path.\r
93e3992d 3782 //\r
84f9a9ec
LG
3783 if (DriverHandle == NULL) {\r
3784 TempDevicePath = DevicePath;\r
3785 Status = gBS->LocateDevicePath (\r
3786 &gEfiDevicePathProtocolGuid,\r
3787 &TempDevicePath,\r
3788 &DriverHandle\r
3789 );\r
3790 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
3791 //\r
3792 // Routing data does not match any known driver.\r
3793 // Set Progress to the 'G' in "GUID" of the routing header.\r
3794 //\r
3795 *Progress = StringPtr;\r
3796 Status = EFI_NOT_FOUND;\r
3797 goto Done;\r
3798 }\r
3799 }\r
82e8c138
ED
3800\r
3801 //\r
3802 // Validate ConfigRequest String.\r
3803 //\r
3804 ErrorPtr = ConfigRequestValidate(ConfigRequest);\r
3805 if (ErrorPtr != NULL) {\r
3806 *Progress = StrStr (StringPtr, ErrorPtr);\r
3807 Status = EFI_INVALID_PARAMETER;\r
3808 goto Done;\r
3809 }\r
3810\r
84f9a9ec 3811 //\r
82e8c138 3812 // Check whether ConfigRequest contains request string.\r
84f9a9ec 3813 //\r
6e3f5b2a 3814 IfrDataParsedFlag = FALSE;\r
82e8c138 3815 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {\r
93e3992d 3816 //\r
84f9a9ec 3817 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 3818 //\r
6e3f5b2a 3819 IfrDataParsedFlag = TRUE;\r
ae79d2f9 3820 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 3821 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
3822 //\r
3823 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3824 // Map it to the progress on <MultiConfigRequest> then return it.\r
3825 //\r
82e8c138 3826 ASSERT (AccessProgress != NULL);\r
ae79d2f9 3827 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
3828 goto Done;\r
3829 }\r
1f1cb2f2
LG
3830 //\r
3831 // Not any request block is found.\r
3832 //\r
82e8c138 3833 if (!GetElementsFromRequest(ConfigRequest)) {\r
76c24251 3834 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
3835 goto NextConfigString;\r
3836 }\r
93e3992d 3837 }\r
3838\r
3839 //\r
cce6230f 3840 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 3841 //\r
cce6230f
ED
3842 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
3843 if (EFI_ERROR (Status)) {\r
3844 goto Done;\r
3845 }\r
3846 \r
3847 if (IsEfiVarStore) {\r
3848 //\r
3849 // Call the GetVariable function to extract settings.\r
3850 //\r
3851 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
82e8c138 3852 FreePool (EfiVarStoreInfo);\r
cce6230f
ED
3853 } else {\r
3854 //\r
3855 // Call corresponding ConfigAccess protocol to extract settings\r
3856 //\r
3857 Status = gBS->HandleProtocol (\r
3858 DriverHandle,\r
3859 &gEfiHiiConfigAccessProtocolGuid,\r
3860 (VOID **) &ConfigAccess\r
3861 );\r
3862 ASSERT_EFI_ERROR (Status);\r
93e3992d 3863\r
cce6230f
ED
3864 Status = ConfigAccess->ExtractConfig (\r
3865 ConfigAccess,\r
3866 ConfigRequest,\r
3867 &AccessProgress,\r
3868 &AccessResults\r
3869 );\r
3870 }\r
93e3992d 3871 if (EFI_ERROR (Status)) {\r
3872 //\r
3873 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3874 // Map it to the progress on <MultiConfigRequest> then return it.\r
3875 //\r
8d00a0f1 3876 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 3877 goto Done;\r
93e3992d 3878 }\r
3879\r
3880 //\r
8d00a0f1 3881 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3882 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 3883 //\r
3884 ASSERT (*AccessProgress == 0);\r
8d00a0f1 3885\r
84f9a9ec
LG
3886 //\r
3887 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3888 //\r
ae79d2f9
LG
3889 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
3890 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3891 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3892 }\r
ae79d2f9 3893\r
84f9a9ec
LG
3894 FreePool (DevicePath);\r
3895 DevicePath = NULL;\r
84f9a9ec 3896\r
ae79d2f9
LG
3897 if (DefaultResults != NULL) {\r
3898 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3899 ASSERT_EFI_ERROR (Status);\r
3900 FreePool (DefaultResults);\r
3901 DefaultResults = NULL;\r
3902 }\r
3903 \r
82e8c138 3904NextConfigString:\r
8d00a0f1 3905 if (!FirstElement) {\r
3906 Status = AppendToMultiString (Results, L"&");\r
3907 ASSERT_EFI_ERROR (Status);\r
3908 }\r
3909 \r
93e3992d 3910 Status = AppendToMultiString (Results, AccessResults);\r
3911 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 3912\r
3913 FirstElement = FALSE;\r
84f9a9ec 3914\r
676df92c 3915 FreePool (AccessResults);\r
93e3992d 3916 AccessResults = NULL;\r
676df92c 3917 FreePool (ConfigRequest);\r
93e3992d 3918 ConfigRequest = NULL;\r
3919\r
3920 //\r
3921 // Go to next <ConfigRequest> (skip '&').\r
3922 //\r
3923 StringPtr += Length;\r
3924 if (*StringPtr == 0) {\r
3925 *Progress = StringPtr;\r
3926 break;\r
3927 }\r
3928\r
3929 StringPtr++;\r
93e3992d 3930 }\r
3931\r
84f9a9ec
LG
3932Done:\r
3933 if (EFI_ERROR (Status)) {\r
3934 FreePool (*Results);\r
6e3f5b2a 3935 *Results = NULL;\r
84f9a9ec
LG
3936 }\r
3937 \r
3938 if (ConfigRequest != NULL) {\r
3939 FreePool (ConfigRequest);\r
3940 }\r
3941 \r
3942 if (AccessResults != NULL) {\r
3943 FreePool (AccessResults);\r
3944 }\r
3945 \r
3946 if (DefaultResults != NULL) {\r
3947 FreePool (DefaultResults);\r
3948 }\r
3949 \r
3950 if (DevicePath != NULL) {\r
3951 FreePool (DevicePath);\r
3952 } \r
93e3992d 3953\r
84f9a9ec 3954 return Status;\r
93e3992d 3955}\r
3956\r
3957\r
3958/**\r
3959 This function allows the caller to request the current configuration for the\r
3960 entirety of the current HII database and returns the data in a\r
3961 null-terminated Unicode string.\r
3962\r
3963 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3964 instance.\r
3965 @param Results Null-terminated Unicode string in\r
3966 <MultiConfigAltResp> format which has all values\r
c0a3c3da
ED
3967 filled in for the entirety of the current HII \r
3968 database. String to be allocated by the called \r
3969 function. De-allocation is up to the caller.\r
93e3992d 3970\r
3971 @retval EFI_SUCCESS The Results string is filled with the values\r
3972 corresponding to all requested names.\r
3973 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3974 results that must be stored awaiting possible\r
3975 future protocols.\r
3976 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
3977 parameter would result in this type of error.\r
3978\r
3979**/\r
3980EFI_STATUS\r
3981EFIAPI\r
3982HiiConfigRoutingExportConfig (\r
3983 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3984 OUT EFI_STRING *Results\r
3985 )\r
3986{\r
93e3992d 3987 EFI_STATUS Status;\r
93e3992d 3988 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
3989 EFI_STRING AccessResults;\r
3990 EFI_STRING Progress;\r
6e3f5b2a 3991 EFI_STRING StringPtr;\r
ae79d2f9 3992 EFI_STRING ConfigRequest;\r
8d00a0f1 3993 UINTN Index;\r
3994 EFI_HANDLE *ConfigAccessHandles;\r
3995 UINTN NumberConfigAccessHandles;\r
3996 BOOLEAN FirstElement;\r
84f9a9ec
LG
3997 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3998 EFI_HII_HANDLE HiiHandle;\r
3999 EFI_STRING DefaultResults;\r
4000 HII_DATABASE_PRIVATE_DATA *Private;\r
4001 LIST_ENTRY *Link;\r
4002 HII_DATABASE_RECORD *Database;\r
4003 UINT8 *DevicePathPkg;\r
4004 UINT8 *CurrentDevicePath;\r
ae79d2f9 4005 BOOLEAN IfrDataParsedFlag;\r
93e3992d 4006\r
4007 if (This == NULL || Results == NULL) {\r
4008 return EFI_INVALID_PARAMETER;\r
4009 }\r
4010\r
84f9a9ec
LG
4011 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4012\r
93e3992d 4013 //\r
4014 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4015 // Results if this fix length is insufficient.\r
4016 //\r
4017 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4018 if (*Results == NULL) {\r
4019 return EFI_OUT_OF_RESOURCES;\r
4020 }\r
4021\r
8d00a0f1 4022 NumberConfigAccessHandles = 0;\r
4023 Status = gBS->LocateHandleBuffer (\r
4024 ByProtocol,\r
4025 &gEfiHiiConfigAccessProtocolGuid,\r
4026 NULL,\r
4027 &NumberConfigAccessHandles,\r
4028 &ConfigAccessHandles\r
4029 );\r
4030 if (EFI_ERROR (Status)) {\r
4031 return Status;\r
4032 }\r
93e3992d 4033\r
8d00a0f1 4034 FirstElement = TRUE;\r
93e3992d 4035\r
8d00a0f1 4036 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 4037 Status = gBS->HandleProtocol (\r
8d00a0f1 4038 ConfigAccessHandles[Index],\r
93e3992d 4039 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 4040 (VOID **) &ConfigAccess\r
93e3992d 4041 );\r
8d00a0f1 4042 if (EFI_ERROR (Status)) {\r
4043 continue;\r
4044 }\r
93e3992d 4045\r
84f9a9ec
LG
4046 //\r
4047 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
4048 //\r
ae79d2f9 4049 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
4050 Progress = NULL;\r
4051 HiiHandle = NULL;\r
84f9a9ec 4052 DefaultResults = NULL;\r
8567300a 4053 Database = NULL;\r
ae79d2f9 4054 ConfigRequest = NULL;\r
84f9a9ec 4055 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
4056 if (DevicePath != NULL) {\r
4057 for (Link = Private->DatabaseList.ForwardLink;\r
4058 Link != &Private->DatabaseList;\r
4059 Link = Link->ForwardLink\r
4060 ) {\r
4061 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4062 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4063 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 4064 if (CompareMem (\r
84f9a9ec
LG
4065 DevicePath,\r
4066 CurrentDevicePath,\r
6e3f5b2a
LG
4067 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
4068 ) == 0) {\r
84f9a9ec
LG
4069 HiiHandle = Database->Handle;\r
4070 break;\r
4071 }\r
4072 }\r
4073 }\r
4074 }\r
4075\r
93e3992d 4076 Status = ConfigAccess->ExtractConfig (\r
4077 ConfigAccess,\r
6e3f5b2a 4078 NULL,\r
84f9a9ec 4079 &Progress,\r
93e3992d 4080 &AccessResults\r
4081 );\r
ae79d2f9 4082 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
4083 //\r
4084 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
4085 //\r
4086 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
4087 IfrDataParsedFlag = TRUE;\r
4088 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
4089 //\r
4090 // Get the full request string to get the Current setting again.\r
4091 //\r
4092 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
4093 Status = ConfigAccess->ExtractConfig (\r
4094 ConfigAccess,\r
4095 ConfigRequest,\r
4096 &Progress,\r
4097 &AccessResults\r
4098 );\r
4099 FreePool (ConfigRequest);\r
4100 } else {\r
4101 Status = EFI_NOT_FOUND;\r
4102 }\r
4103 }\r
4104 }\r
4105\r
4106 if (!EFI_ERROR (Status)) {\r
4107 //\r
4108 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
4109 //\r
4110 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
4111 StringPtr = StrStr (AccessResults, L"&GUID=");\r
4112 if (StringPtr != NULL) {\r
4113 *StringPtr = 0;\r
4114 }\r
82e8c138 4115 if (GetElementsFromRequest (AccessResults)) {\r
ae79d2f9
LG
4116 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
4117 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
4118 }\r
4119 if (StringPtr != NULL) {\r
4120 *StringPtr = L'&';\r
4121 }\r
4122 }\r
84f9a9ec
LG
4123 //\r
4124 // Merge the default sting from IFR code into the got setting from driver.\r
4125 //\r
4126 if (DefaultResults != NULL) {\r
8567300a
LG
4127 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
4128 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 4129 FreePool (DefaultResults);\r
8567300a 4130 DefaultResults = NULL;\r
84f9a9ec
LG
4131 }\r
4132 \r
8d00a0f1 4133 //\r
4134 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4135 // which seperates the first <ConfigAltResp> and the following ones. \r
4136 //\r
4137 if (!FirstElement) {\r
4138 Status = AppendToMultiString (Results, L"&");\r
4139 ASSERT_EFI_ERROR (Status);\r
676df92c 4140 }\r
8d00a0f1 4141 \r
4142 Status = AppendToMultiString (Results, AccessResults);\r
4143 ASSERT_EFI_ERROR (Status);\r
93e3992d 4144\r
8d00a0f1 4145 FirstElement = FALSE;\r
4146 \r
4147 FreePool (AccessResults);\r
4148 AccessResults = NULL;\r
4149 }\r
93e3992d 4150 }\r
f4113e1f 4151 FreePool (ConfigAccessHandles);\r
93e3992d 4152\r
8d00a0f1 4153 return EFI_SUCCESS; \r
93e3992d 4154}\r
4155\r
4156\r
4157/**\r
4158 This function processes the results of processing forms and routes it to the\r
4159 appropriate handlers or storage.\r
4160\r
4161 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4162 instance.\r
4163 @param Configuration A null-terminated Unicode string in\r
4164 <MulltiConfigResp> format.\r
4165 @param Progress A pointer to a string filled in with the offset of\r
4166 the most recent & before the first failing name /\r
4167 value pair (or the beginning of the string if the\r
4168 failure is in the first name / value pair) or the\r
4169 terminating NULL if all was successful.\r
4170\r
4171 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
4172 distribution.\r
4173 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
4174 results that must be stored awaiting possible\r
4175 future protocols.\r
4176 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
4177 would result in this type of error.\r
4178 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4179 found.\r
4180\r
4181**/\r
4182EFI_STATUS\r
4183EFIAPI\r
813acf3a 4184HiiConfigRoutingRouteConfig (\r
93e3992d 4185 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4186 IN CONST EFI_STRING Configuration,\r
4187 OUT EFI_STRING *Progress\r
4188 )\r
4189{\r
84f9a9ec 4190 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4191 EFI_STRING StringPtr;\r
4192 EFI_STRING ConfigResp;\r
4193 UINTN Length;\r
4194 EFI_STATUS Status;\r
4195 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 4196 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
4197 LIST_ENTRY *Link;\r
4198 HII_DATABASE_RECORD *Database;\r
4199 UINT8 *DevicePathPkg;\r
4200 UINT8 *CurrentDevicePath;\r
93e3992d 4201 EFI_HANDLE DriverHandle;\r
4202 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4203 EFI_STRING AccessProgress;\r
cce6230f
ED
4204 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4205 BOOLEAN IsEfiVarstore;\r
7248790e 4206 UINTN DevicePathSize;\r
93e3992d 4207\r
4208 if (This == NULL || Progress == NULL) {\r
4209 return EFI_INVALID_PARAMETER;\r
4210 }\r
4211\r
4212 if (Configuration == NULL) {\r
4213 *Progress = NULL;\r
4214 return EFI_INVALID_PARAMETER;\r
4215 }\r
4216\r
84f9a9ec 4217 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 4218 StringPtr = Configuration;\r
4219 *Progress = StringPtr;\r
cce6230f
ED
4220 Database = NULL;\r
4221 AccessProgress = NULL;\r
4222 EfiVarStoreInfo= NULL;\r
4223 IsEfiVarstore = FALSE;\r
93e3992d 4224\r
4225 //\r
4226 // The first element of <MultiConfigResp> should be\r
4227 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4228 //\r
4229 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4230 return EFI_INVALID_PARAMETER;\r
4231 }\r
4232\r
4233 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4234 //\r
4235 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
4236 // or most recent & before the error.\r
4237 //\r
4238 if (StringPtr == Configuration) {\r
4239 *Progress = StringPtr;\r
4240 } else {\r
4241 *Progress = StringPtr - 1;\r
4242 }\r
4243\r
4244 //\r
4245 // Process each <ConfigResp> of <MultiConfigResp>\r
4246 //\r
4247 Length = CalculateConfigStringLen (StringPtr);\r
4248 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4249 if (ConfigResp == NULL) {\r
4250 return EFI_OUT_OF_RESOURCES;\r
4251 }\r
4252 //\r
4253 // Append '\0' to the end of ConfigRequest\r
4254 //\r
4255 *(ConfigResp + Length) = 0;\r
4256\r
4257 //\r
4258 // Get the UEFI device path\r
4259 //\r
4260 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
4261 if (EFI_ERROR (Status)) {\r
676df92c 4262 FreePool (ConfigResp);\r
93e3992d 4263 return Status;\r
4264 }\r
4265\r
4266 //\r
84f9a9ec
LG
4267 // Find driver which matches the routing data.\r
4268 //\r
4269 DriverHandle = NULL;\r
84f9a9ec
LG
4270 for (Link = Private->DatabaseList.ForwardLink;\r
4271 Link != &Private->DatabaseList;\r
4272 Link = Link->ForwardLink\r
4273 ) {\r
4274 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4275\r
4276 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4277 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
7248790e 4278 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
8aaab674 4279 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {\r
84f9a9ec
LG
4280 DriverHandle = Database->DriverHandle;\r
4281 break;\r
4282 }\r
4283 }\r
4284 }\r
93e3992d 4285\r
84f9a9ec
LG
4286 //\r
4287 // Try to find driver handle by device path.\r
4288 //\r
4289 if (DriverHandle == NULL) {\r
4290 TempDevicePath = DevicePath;\r
4291 Status = gBS->LocateDevicePath (\r
4292 &gEfiDevicePathProtocolGuid,\r
4293 &TempDevicePath,\r
4294 &DriverHandle\r
4295 );\r
4296 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4297 //\r
4298 // Routing data does not match any known driver.\r
4299 // Set Progress to the 'G' in "GUID" of the routing header.\r
4300 //\r
4301 FreePool (DevicePath);\r
4302 *Progress = StringPtr;\r
4303 FreePool (ConfigResp);\r
4304 return EFI_NOT_FOUND;\r
4305 }\r
93e3992d 4306 }\r
4307\r
84f9a9ec
LG
4308 FreePool (DevicePath);\r
4309\r
93e3992d 4310 //\r
cce6230f 4311 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 4312 //\r
cce6230f
ED
4313 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
4314 if (EFI_ERROR (Status)) {\r
4315 return Status;\r
4316 }\r
93e3992d 4317\r
cce6230f
ED
4318 if (IsEfiVarstore) {\r
4319 //\r
4320 // Call the SetVariable function to route settings.\r
4321 // \r
4322 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
4323 FreePool (EfiVarStoreInfo);\r
4324 } else {\r
4325 //\r
4326 // Call corresponding ConfigAccess protocol to route settings\r
4327 //\r
4328 Status = gBS->HandleProtocol (\r
4329 DriverHandle,\r
4330 &gEfiHiiConfigAccessProtocolGuid,\r
4331 (VOID **) &ConfigAccess\r
4332 );\r
4333 ASSERT_EFI_ERROR (Status);\r
93e3992d 4334\r
cce6230f
ED
4335 Status = ConfigAccess->RouteConfig (\r
4336 ConfigAccess,\r
4337 ConfigResp,\r
4338 &AccessProgress\r
4339 );\r
4340 }\r
93e3992d 4341 if (EFI_ERROR (Status)) {\r
4342 //\r
4343 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
4344 // Map it to the progress on <MultiConfigResp> then return it.\r
4345 //\r
8d00a0f1 4346 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 4347\r
676df92c 4348 FreePool (ConfigResp);\r
93e3992d 4349 return Status;\r
4350 }\r
4351\r
676df92c 4352 FreePool (ConfigResp);\r
93e3992d 4353 ConfigResp = NULL;\r
4354\r
4355 //\r
4356 // Go to next <ConfigResp> (skip '&').\r
4357 //\r
4358 StringPtr += Length;\r
4359 if (*StringPtr == 0) {\r
4360 *Progress = StringPtr;\r
4361 break;\r
4362 }\r
4363\r
4364 StringPtr++;\r
4365\r
4366 }\r
4367\r
4368 return EFI_SUCCESS;\r
93e3992d 4369}\r
4370\r
4371\r
4372/**\r
4373 This helper function is to be called by drivers to map configuration data\r
4374 stored in byte array ("block") formats such as UEFI Variables into current\r
4375 configuration strings.\r
4376\r
4377 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4378 instance.\r
4379 @param ConfigRequest A null-terminated Unicode string in\r
4380 <ConfigRequest> format.\r
4381 @param Block Array of bytes defining the block's configuration.\r
4382 @param BlockSize Length in bytes of Block.\r
4383 @param Config Filled-in configuration string. String allocated\r
4384 by the function. Returned only if call is\r
84f9a9ec 4385 successful. It is <ConfigResp> string format.\r
93e3992d 4386 @param Progress A pointer to a string filled in with the offset of\r
4387 the most recent & before the first failing\r
4388 name/value pair (or the beginning of the string if\r
4389 the failure is in the first name / value pair) or\r
4390 the terminating NULL if all was successful.\r
4391\r
4392 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4393 terminator at the end of the ConfigRequest\r
4394 string.\r
4395 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4396 points to the first character of ConfigRequest.\r
4397 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
4398 Block parameter would result in this type of\r
4399 error. Progress points to the first character of\r
4400 ConfigRequest.\r
4401 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4402 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
4403 Block is left updated and Progress points at\r
4404 the "&" preceding the first non-<BlockName>.\r
4405\r
4406**/\r
4407EFI_STATUS\r
4408EFIAPI\r
4409HiiBlockToConfig (\r
4410 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4411 IN CONST EFI_STRING ConfigRequest,\r
4412 IN CONST UINT8 *Block,\r
4413 IN CONST UINTN BlockSize,\r
4414 OUT EFI_STRING *Config,\r
4415 OUT EFI_STRING *Progress\r
4416 )\r
4417{\r
84f9a9ec 4418 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4419 EFI_STRING StringPtr;\r
4420 UINTN Length;\r
4421 EFI_STATUS Status;\r
4422 EFI_STRING TmpPtr;\r
4423 UINT8 *TmpBuffer;\r
4424 UINTN Offset;\r
4425 UINTN Width;\r
4426 UINT8 *Value;\r
4427 EFI_STRING ValueStr;\r
4428 EFI_STRING ConfigElement;\r
63d55bb9
LG
4429 UINTN Index;\r
4430 UINT8 *TemBuffer;\r
4431 CHAR16 *TemString;\r
41ff10dc 4432 CHAR16 TemChar;\r
93e3992d 4433\r
4434 if (This == NULL || Progress == NULL || Config == NULL) {\r
4435 return EFI_INVALID_PARAMETER;\r
4436 }\r
4437\r
4438 if (Block == NULL || ConfigRequest == NULL) {\r
4439 *Progress = ConfigRequest;\r
4440 return EFI_INVALID_PARAMETER;\r
4441 }\r
4442\r
84f9a9ec
LG
4443\r
4444 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4445 ASSERT (Private != NULL);\r
4446\r
93e3992d 4447 StringPtr = ConfigRequest;\r
4448 ValueStr = NULL;\r
4449 Value = NULL;\r
4450 ConfigElement = NULL;\r
4451\r
4452 //\r
4453 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4454 // Results if this fix length is insufficient.\r
4455 //\r
4456 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4457 if (*Config == NULL) {\r
4458 return EFI_OUT_OF_RESOURCES;\r
4459 }\r
4460\r
4461 //\r
4462 // Jump <ConfigHdr>\r
4463 //\r
4464 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4465 *Progress = StringPtr;\r
4466 Status = EFI_INVALID_PARAMETER;\r
4467 goto Exit;\r
4468 }\r
4469 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4470 StringPtr++;\r
4471 }\r
4472 if (*StringPtr == 0) {\r
76c24251 4473 *Progress = StringPtr - 1;\r
93e3992d 4474 Status = EFI_INVALID_PARAMETER;\r
4475 goto Exit;\r
4476 }\r
08e6463a 4477\r
4478 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4479 StringPtr++;\r
4480 }\r
4481 if (*StringPtr == 0) {\r
41ff10dc 4482 *Progress = StringPtr;\r
41ff10dc
ED
4483\r
4484 AppendToMultiString(Config, ConfigRequest);\r
4485 HiiToLower (*Config);\r
4486\r
96179cb3 4487 return EFI_SUCCESS;\r
08e6463a 4488 }\r
4489 //\r
4490 // Skip '&'\r
4491 //\r
4492 StringPtr++;\r
93e3992d 4493\r
4494 //\r
4495 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
4496 //\r
41ff10dc
ED
4497 TemChar = *StringPtr;\r
4498 *StringPtr = '\0';\r
4499 AppendToMultiString(Config, ConfigRequest);\r
4500 *StringPtr = TemChar;\r
93e3992d 4501\r
4502 //\r
4503 // Parse each <RequestElement> if exists\r
4504 // Only <BlockName> format is supported by this help function.\r
4505 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
4506 //\r
4507 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
4508 //\r
4509 // Back up the header of one <BlockName>\r
4510 //\r
4511 TmpPtr = StringPtr;\r
4512\r
4513 StringPtr += StrLen (L"OFFSET=");\r
4514 //\r
4515 // Get Offset\r
4516 //\r
4517 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4518 if (EFI_ERROR (Status)) {\r
46c3efbb 4519 *Progress = TmpPtr - 1;\r
93e3992d 4520 goto Exit;\r
4521 }\r
4522 Offset = 0;\r
4523 CopyMem (\r
4524 &Offset,\r
4525 TmpBuffer,\r
4526 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4527 );\r
676df92c 4528 FreePool (TmpBuffer);\r
93e3992d 4529\r
4530 StringPtr += Length;\r
4531 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 4532 *Progress = TmpPtr - 1;\r
93e3992d 4533 Status = EFI_INVALID_PARAMETER;\r
4534 goto Exit;\r
4535 }\r
4536 StringPtr += StrLen (L"&WIDTH=");\r
4537\r
4538 //\r
4539 // Get Width\r
4540 //\r
4541 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4542 if (EFI_ERROR (Status)) {\r
46c3efbb 4543 *Progress = TmpPtr - 1;\r
93e3992d 4544 goto Exit;\r
4545 }\r
4546 Width = 0;\r
4547 CopyMem (\r
4548 &Width,\r
4549 TmpBuffer,\r
4550 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4551 );\r
676df92c 4552 FreePool (TmpBuffer);\r
93e3992d 4553\r
4554 StringPtr += Length;\r
4555 if (*StringPtr != 0 && *StringPtr != L'&') {\r
46c3efbb 4556 *Progress = TmpPtr - 1;\r
93e3992d 4557 Status = EFI_INVALID_PARAMETER;\r
4558 goto Exit;\r
4559 }\r
4560\r
4561 //\r
4562 // Calculate Value and convert it to hex string.\r
4563 //\r
4564 if (Offset + Width > BlockSize) {\r
4565 *Progress = StringPtr;\r
4566 Status = EFI_DEVICE_ERROR;\r
4567 goto Exit;\r
4568 }\r
4569\r
4570 Value = (UINT8 *) AllocateZeroPool (Width);\r
4571 if (Value == NULL) {\r
4572 *Progress = ConfigRequest;\r
4573 Status = EFI_OUT_OF_RESOURCES;\r
4574 goto Exit;\r
4575 }\r
4576\r
4577 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
4578\r
4579 Length = Width * 2 + 1;\r
4580 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4581 if (ValueStr == NULL) {\r
4582 *Progress = ConfigRequest;\r
4583 Status = EFI_OUT_OF_RESOURCES;\r
4584 goto Exit;\r
4585 }\r
63d55bb9
LG
4586 \r
4587 TemString = ValueStr;\r
4588 TemBuffer = Value + Width - 1;\r
4589 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
4590 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
4591 }\r
813acf3a 4592\r
676df92c 4593 FreePool (Value);\r
93e3992d 4594 Value = NULL;\r
4595\r
4596 //\r
4597 // Build a ConfigElement\r
4598 //\r
4599 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
4600 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4601 if (ConfigElement == NULL) {\r
4602 Status = EFI_OUT_OF_RESOURCES;\r
4603 goto Exit;\r
4604 }\r
4605 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
4606 if (*StringPtr == 0) {\r
4607 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
4608 }\r
4609 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
4610 StrCat (ConfigElement, L"VALUE=");\r
4611 StrCat (ConfigElement, ValueStr);\r
4612\r
4613 AppendToMultiString (Config, ConfigElement);\r
4614\r
676df92c 4615 FreePool (ConfigElement);\r
4616 FreePool (ValueStr);\r
93e3992d 4617 ConfigElement = NULL;\r
4618 ValueStr = NULL;\r
4619\r
4620 //\r
4621 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
4622 //\r
4623 if (*StringPtr == 0) {\r
4624 break;\r
4625 }\r
4626 AppendToMultiString (Config, L"&");\r
4627 StringPtr++;\r
4628\r
4629 }\r
4630\r
4631 if (*StringPtr != 0) {\r
4632 *Progress = StringPtr - 1;\r
4633 Status = EFI_INVALID_PARAMETER;\r
4634 goto Exit;\r
4635 }\r
84f9a9ec
LG
4636 \r
4637 HiiToLower (*Config);\r
93e3992d 4638 *Progress = StringPtr;\r
4639 return EFI_SUCCESS;\r
4640\r
4641Exit:\r
76c24251 4642 if (*Config != NULL) {\r
1f1cb2f2
LG
4643 FreePool (*Config);\r
4644 *Config = NULL;\r
76c24251 4645 }\r
676df92c 4646 if (ValueStr != NULL) {\r
4647 FreePool (ValueStr);\r
4648 }\r
4649 if (Value != NULL) {\r
4650 FreePool (Value);\r
4651 }\r
69367b5b 4652 if (ConfigElement != NULL) {\r
676df92c 4653 FreePool (ConfigElement);\r
4654 }\r
93e3992d 4655\r
4656 return Status;\r
4657\r
4658}\r
4659\r
4660\r
4661/**\r
4662 This helper function is to be called by drivers to map configuration strings\r
4663 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
4664\r
4665 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4666 instance.\r
4667 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 4668 format.\r
93e3992d 4669 @param Block A possibly null array of bytes representing the\r
4670 current block. Only bytes referenced in the\r
4671 ConfigResp string in the block are modified. If\r
4672 this parameter is null or if the *BlockSize\r
4673 parameter is (on input) shorter than required by\r
4674 the Configuration string, only the BlockSize\r
4675 parameter is updated and an appropriate status\r
4676 (see below) is returned.\r
4677 @param BlockSize The length of the Block in units of UINT8. On\r
4678 input, this is the size of the Block. On output,\r
c0a3c3da
ED
4679 if successful, contains the largest index of the\r
4680 modified byte in the Block, or the required buffer\r
4681 size if the Block is not large enough.\r
93e3992d 4682 @param Progress On return, points to an element of the ConfigResp\r
4683 string filled in with the offset of the most\r
4684 recent '&' before the first failing name / value\r
4685 pair (or the beginning of the string if the\r
4686 failure is in the first name / value pair) or the\r
4687 terminating NULL if all was successful.\r
4688\r
4689 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4690 terminator at the end of the ConfigResp string.\r
4691 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4692 points to the first character of ConfigResp.\r
4693 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
4694 Block parameter would result in this type of\r
4695 error. Progress points to the first character of\r
4696 ConfigResp.\r
4697 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
4698 value pair. Block is left updated and\r
4699 Progress points at the '&' preceding the first\r
4700 non-<BlockName>.\r
c0a3c3da
ED
4701 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined. \r
4702 BlockSize is updated with the required buffer size.\r
09b79417
LG
4703 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
4704 Progress points to the "G" in "GUID" of the errant\r
4705 routing data.\r
93e3992d 4706\r
4707**/\r
4708EFI_STATUS\r
4709EFIAPI\r
4710HiiConfigToBlock (\r
4711 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4712 IN CONST EFI_STRING ConfigResp,\r
4713 IN OUT UINT8 *Block,\r
4714 IN OUT UINTN *BlockSize,\r
4715 OUT EFI_STRING *Progress\r
4716 )\r
4717{\r
4718 HII_DATABASE_PRIVATE_DATA *Private;\r
4719 EFI_STRING StringPtr;\r
46c3efbb 4720 EFI_STRING TmpPtr;\r
93e3992d 4721 UINTN Length;\r
4722 EFI_STATUS Status;\r
4723 UINT8 *TmpBuffer;\r
4724 UINTN Offset;\r
4725 UINTN Width;\r
4726 UINT8 *Value;\r
4727 UINTN BufferSize;\r
09b79417 4728 UINTN MaxBlockSize;\r
93e3992d 4729\r
4730 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
4731 return EFI_INVALID_PARAMETER;\r
4732 }\r
4733\r
09b79417
LG
4734 *Progress = ConfigResp;\r
4735 if (ConfigResp == NULL) {\r
93e3992d 4736 return EFI_INVALID_PARAMETER;\r
4737 }\r
4738\r
4739 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4740 ASSERT (Private != NULL);\r
4741\r
4742 StringPtr = ConfigResp;\r
4743 BufferSize = *BlockSize;\r
4744 Value = NULL;\r
09b79417 4745 MaxBlockSize = 0;\r
93e3992d 4746\r
4747 //\r
4748 // Jump <ConfigHdr>\r
4749 //\r
4750 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4751 *Progress = StringPtr;\r
4752 Status = EFI_INVALID_PARAMETER;\r
4753 goto Exit;\r
4754 }\r
4755 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4756 StringPtr++;\r
4757 }\r
4758 if (*StringPtr == 0) {\r
4759 *Progress = StringPtr;\r
4760 Status = EFI_INVALID_PARAMETER;\r
4761 goto Exit;\r
4762 }\r
08e6463a 4763\r
4764 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4765 StringPtr++;\r
4766 }\r
4767 if (*StringPtr == 0) {\r
4768 *Progress = StringPtr;\r
4769 Status = EFI_INVALID_PARAMETER;\r
4770 goto Exit;\r
4771 }\r
93e3992d 4772\r
4773 //\r
4774 // Parse each <ConfigElement> if exists\r
edae8d2d 4775 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 4776 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
4777 //\r
edae8d2d 4778 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
46c3efbb 4779 TmpPtr = StringPtr;\r
edae8d2d 4780 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 4781 //\r
4782 // Get Offset\r
4783 //\r
4784 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 4785 if (EFI_ERROR (Status)) {\r
46c3efbb 4786 *Progress = TmpPtr;\r
93e3992d 4787 goto Exit;\r
4788 }\r
4789 Offset = 0;\r
4790 CopyMem (\r
4791 &Offset,\r
4792 TmpBuffer,\r
4793 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4794 );\r
676df92c 4795 FreePool (TmpBuffer);\r
93e3992d 4796\r
4797 StringPtr += Length;\r
4798 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 4799 *Progress = TmpPtr;\r
93e3992d 4800 Status = EFI_INVALID_PARAMETER;\r
4801 goto Exit;\r
4802 }\r
4803 StringPtr += StrLen (L"&WIDTH=");\r
4804\r
4805 //\r
4806 // Get Width\r
4807 //\r
4808 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 4809 if (EFI_ERROR (Status)) {\r
46c3efbb 4810 *Progress = TmpPtr;\r
93e3992d 4811 goto Exit;\r
4812 }\r
4813 Width = 0;\r
4814 CopyMem (\r
4815 &Width,\r
4816 TmpBuffer,\r
4817 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4818 );\r
676df92c 4819 FreePool (TmpBuffer);\r
93e3992d 4820\r
4821 StringPtr += Length;\r
4822 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
46c3efbb 4823 *Progress = TmpPtr;\r
93e3992d 4824 Status = EFI_INVALID_PARAMETER;\r
4825 goto Exit;\r
4826 }\r
4827 StringPtr += StrLen (L"&VALUE=");\r
4828\r
4829 //\r
4830 // Get Value\r
4831 //\r
4832 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 4833 if (EFI_ERROR (Status)) {\r
46c3efbb 4834 *Progress = TmpPtr;\r
93e3992d 4835 goto Exit;\r
4836 }\r
4837\r
4838 StringPtr += Length;\r
4839 if (*StringPtr != 0 && *StringPtr != L'&') {\r
46c3efbb 4840 *Progress = TmpPtr;\r
93e3992d 4841 Status = EFI_INVALID_PARAMETER;\r
4842 goto Exit;\r
4843 }\r
4844\r
4845 //\r
4846 // Update the Block with configuration info\r
4847 //\r
09b79417
LG
4848 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
4849 CopyMem (Block + Offset, Value, Width);\r
4850 }\r
4851 if (Offset + Width > MaxBlockSize) {\r
4852 MaxBlockSize = Offset + Width;\r
93e3992d 4853 }\r
93e3992d 4854\r
676df92c 4855 FreePool (Value);\r
93e3992d 4856 Value = NULL;\r
4857\r
4858 //\r
edae8d2d 4859 // If '\0', parsing is finished.\r
93e3992d 4860 //\r
4861 if (*StringPtr == 0) {\r
4862 break;\r
4863 }\r
93e3992d 4864 }\r
84f9a9ec
LG
4865 \r
4866 //\r
edae8d2d 4867 // The input string is not ConfigResp format, return error.\r
84f9a9ec 4868 //\r
edae8d2d
ED
4869 if (*StringPtr != 0) {\r
4870 *Progress = StringPtr;\r
93e3992d 4871 Status = EFI_INVALID_PARAMETER;\r
4872 goto Exit;\r
4873 }\r
4874\r
6e3f5b2a 4875 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
4876 *BlockSize = MaxBlockSize - 1;\r
4877\r
4878 if (MaxBlockSize > BufferSize) {\r
4879 *BlockSize = MaxBlockSize;\r
9ac0640d 4880 if (Block != NULL) {\r
c0a3c3da 4881 return EFI_BUFFER_TOO_SMALL;\r
09b79417
LG
4882 }\r
4883 }\r
4884\r
9ac0640d
LG
4885 if (Block == NULL) {\r
4886 *Progress = ConfigResp;\r
4887 return EFI_INVALID_PARAMETER;\r
4888 }\r
4889\r
93e3992d 4890 return EFI_SUCCESS;\r
4891\r
4892Exit:\r
4893\r
676df92c 4894 if (Value != NULL) {\r
4895 FreePool (Value);\r
4896 }\r
93e3992d 4897 return Status;\r
4898}\r
4899\r
4900\r
4901/**\r
4902 This helper function is to be called by drivers to extract portions of\r
4903 a larger configuration string.\r
4904\r
4905 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4906 instance.\r
4907 @param Configuration A null-terminated Unicode string in\r
771ececd 4908 <MultiConfigAltResp> format.\r
93e3992d 4909 @param Guid A pointer to the GUID value to search for in the\r
4910 routing portion of the ConfigResp string when\r
4911 retrieving the requested data. If Guid is NULL,\r
4912 then all GUID values will be searched for.\r
4913 @param Name A pointer to the NAME value to search for in the\r
4914 routing portion of the ConfigResp string when\r
4915 retrieving the requested data. If Name is NULL,\r
4916 then all Name values will be searched for.\r
4917 @param DevicePath A pointer to the PATH value to search for in the\r
4918 routing portion of the ConfigResp string when\r
4919 retrieving the requested data. If DevicePath is\r
4920 NULL, then all DevicePath values will be searched\r
4921 for.\r
4922 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
4923 routing portion of the ConfigResp string when\r
4924 retrieving the requested data. If this parameter\r
4925 is NULL, then the current setting will be\r
4926 retrieved.\r
4927 @param AltCfgResp A pointer to a buffer which will be allocated by\r
4928 the function which contains the retrieved string\r
4929 as requested. This buffer is only allocated if\r
84f9a9ec 4930 the call was successful. It is <ConfigResp> format.\r
93e3992d 4931\r
4932 @retval EFI_SUCCESS The request succeeded. The requested data was\r
4933 extracted and placed in the newly allocated\r
4934 AltCfgResp buffer.\r
4935 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
4936 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
4937 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4938 found.\r
4939\r
4940**/\r
4941EFI_STATUS\r
4942EFIAPI\r
4943HiiGetAltCfg (\r
4944 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4945 IN CONST EFI_STRING Configuration,\r
4946 IN CONST EFI_GUID *Guid,\r
4947 IN CONST EFI_STRING Name,\r
4948 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4949 IN CONST UINT16 *AltCfgId,\r
4950 OUT EFI_STRING *AltCfgResp\r
4951 )\r
4952{\r
93e3992d 4953 EFI_STATUS Status;\r
4954 EFI_STRING StringPtr;\r
e90b081a 4955 EFI_STRING HdrStart;\r
4956 EFI_STRING HdrEnd;\r
93e3992d 4957 EFI_STRING TmpPtr;\r
4958 UINTN Length;\r
e90b081a 4959 EFI_STRING GuidStr;\r
4960 EFI_STRING NameStr;\r
4961 EFI_STRING PathStr;\r
4962 EFI_STRING AltIdStr;\r
4963 EFI_STRING Result;\r
4964 BOOLEAN GuidFlag;\r
4965 BOOLEAN NameFlag;\r
4966 BOOLEAN PathFlag;\r
4967\r
4968 HdrStart = NULL;\r
4969 HdrEnd = NULL;\r
4970 GuidStr = NULL;\r
4971 NameStr = NULL;\r
4972 PathStr = NULL;\r
4973 AltIdStr = NULL;\r
4974 Result = NULL;\r
4975 GuidFlag = FALSE;\r
4976 NameFlag = FALSE;\r
4977 PathFlag = FALSE;\r
93e3992d 4978\r
4979 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
4980 return EFI_INVALID_PARAMETER;\r
4981 }\r
4982\r
4983 StringPtr = Configuration;\r
4984 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4985 return EFI_INVALID_PARAMETER;\r
4986 }\r
4987\r
4988 //\r
4989 // Generate the sub string for later matching.\r
4990 //\r
813acf3a 4991 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 4992 GenerateSubStr (\r
4993 L"PATH=",\r
4994 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 4995 (VOID *) DevicePath,\r
4996 1,\r
93e3992d 4997 &PathStr\r
4998 );\r
4999 if (AltCfgId != NULL) {\r
813acf3a 5000 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 5001 }\r
5002 if (Name != NULL) {\r
813acf3a 5003 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 5004 } else {\r
813acf3a 5005 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 5006 }\r
5007\r
5008 while (*StringPtr != 0) {\r
5009 //\r
5010 // Try to match the GUID\r
5011 //\r
5012 if (!GuidFlag) {\r
5013 TmpPtr = StrStr (StringPtr, GuidStr);\r
5014 if (TmpPtr == NULL) {\r
5015 Status = EFI_NOT_FOUND;\r
5016 goto Exit;\r
5017 }\r
5018 HdrStart = TmpPtr;\r
5019\r
5020 //\r
5021 // Jump to <NameHdr>\r
5022 //\r
5023 if (Guid != NULL) {\r
5024 StringPtr = TmpPtr + StrLen (GuidStr);\r
5025 } else {\r
5026 StringPtr = StrStr (TmpPtr, L"NAME=");\r
5027 if (StringPtr == NULL) {\r
5028 Status = EFI_NOT_FOUND;\r
5029 goto Exit;\r
5030 }\r
5031 }\r
5032 GuidFlag = TRUE;\r
5033 }\r
5034\r
5035 //\r
5036 // Try to match the NAME\r
5037 //\r
5038 if (GuidFlag && !NameFlag) {\r
5039 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
5040 GuidFlag = FALSE;\r
5041 } else {\r
5042 //\r
5043 // Jump to <PathHdr>\r
5044 //\r
5045 if (Name != NULL) {\r
5046 StringPtr += StrLen (NameStr);\r
5047 } else {\r
5048 StringPtr = StrStr (StringPtr, L"PATH=");\r
5049 if (StringPtr == NULL) {\r
5050 Status = EFI_NOT_FOUND;\r
5051 goto Exit;\r
5052 }\r
5053 }\r
5054 NameFlag = TRUE;\r
5055 }\r
5056 }\r
5057\r
5058 //\r
5059 // Try to match the DevicePath\r
5060 //\r
5061 if (GuidFlag && NameFlag && !PathFlag) {\r
5062 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
5063 GuidFlag = FALSE;\r
5064 NameFlag = FALSE;\r
5065 } else {\r
5066 //\r
5067 // Jump to '&' before <DescHdr> or <ConfigBody>\r
5068 //\r
5069 if (DevicePath != NULL) {\r
5070 StringPtr += StrLen (PathStr);\r
5071 } else {\r
5072 StringPtr = StrStr (StringPtr, L"&");\r
5073 if (StringPtr == NULL) {\r
5074 Status = EFI_NOT_FOUND;\r
5075 goto Exit;\r
5076 }\r
84f9a9ec 5077 StringPtr ++;\r
93e3992d 5078 }\r
5079 PathFlag = TRUE;\r
84f9a9ec 5080 HdrEnd = StringPtr;\r
93e3992d 5081 }\r
5082 }\r
5083\r
5084 //\r
5085 // Try to match the AltCfgId\r
5086 //\r
5087 if (GuidFlag && NameFlag && PathFlag) {\r
5088 if (AltCfgId == NULL) {\r
5089 //\r
5090 // Return Current Setting when AltCfgId is NULL.\r
5091 //\r
5092 Status = OutputConfigBody (StringPtr, &Result);\r
5093 goto Exit;\r
5094 }\r
5095 //\r
5096 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
5097 //\r
5098 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
5099 GuidFlag = FALSE;\r
5100 NameFlag = FALSE;\r
5101 PathFlag = FALSE;\r
5102 } else {\r
84f9a9ec
LG
5103 //\r
5104 // Skip AltIdStr and &\r
5105 //\r
5106 StringPtr = StringPtr + StrLen (AltIdStr);\r
5107 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 5108 goto Exit;\r
5109 }\r
5110 }\r
5111 }\r
5112\r
5113 Status = EFI_NOT_FOUND;\r
5114\r
5115Exit:\r
76c24251 5116 *AltCfgResp = NULL;\r
bc166db3 5117 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 5118 //\r
5119 // Copy the <ConfigHdr> and <ConfigBody>\r
5120 //\r
84f9a9ec 5121 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 5122 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
5123 if (*AltCfgResp == NULL) {\r
5124 Status = EFI_OUT_OF_RESOURCES;\r
5125 } else {\r
5126 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
5127 StrCat (*AltCfgResp, Result);\r
5128 Status = EFI_SUCCESS;\r
5129 }\r
5130 }\r
5131\r
676df92c 5132 if (GuidStr != NULL) {\r
5133 FreePool (GuidStr);\r
5134 }\r
5135 if (NameStr != NULL) {\r
5136 FreePool (NameStr);\r
5137 }\r
5138 if (PathStr != NULL) {\r
5139 FreePool (PathStr);\r
5140 }\r
5141 if (AltIdStr != NULL) {\r
5142 FreePool (AltIdStr);\r
5143 }\r
5144 if (Result != NULL) {\r
5145 FreePool (Result);\r
5146 }\r
93e3992d 5147\r
5148 return Status;\r
5149\r
93e3992d 5150}\r
5151\r
36fe40c2 5152\r