]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
Fix a bug in Mtftp6 retransmission mechanism of the ACK.
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
CommitLineData
93e3992d 1/** @file\r
3cb3f198 2Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
93e3992d 3\r
a7f87053 4Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
93e3992d 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
93e3992d 13**/\r
14\r
15\r
16#include "HiiDatabase.h"\r
84f9a9ec 17extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
93e3992d 18\r
93e3992d 19/**\r
20 Calculate the number of Unicode characters of the incoming Configuration string,\r
21 not including NULL terminator.\r
22\r
e90b081a 23 This is a internal function.\r
24\r
93e3992d 25 @param String String in <MultiConfigRequest> or\r
26 <MultiConfigResp> format.\r
27\r
28 @return The number of Unicode characters.\r
29\r
30**/\r
93e3992d 31UINTN\r
32CalculateConfigStringLen (\r
33 IN EFI_STRING String\r
34 )\r
35{\r
84f9a9ec 36 EFI_STRING TmpPtr;\r
93e3992d 37\r
38 //\r
39 // "GUID=" should be the first element of incoming string.\r
40 //\r
41 ASSERT (String != NULL);\r
42 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
43\r
93e3992d 44 //\r
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
84f9a9ec
LG
47 // \r
48 TmpPtr = StrStr (String, L"&GUID=");\r
49 if (TmpPtr == NULL) {\r
50 return StrLen (String);\r
93e3992d 51 }\r
52\r
84f9a9ec 53 return (TmpPtr - String);\r
93e3992d 54}\r
55\r
56\r
57/**\r
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
59 from <PathHdr> of <ConfigHdr>.\r
60\r
e90b081a 61 This is a internal function.\r
62\r
93e3992d 63 @param String UEFI configuration string\r
ae79d2f9 64 @param DevicePathData Binary of a UEFI device path.\r
93e3992d 65\r
ae79d2f9 66 @retval EFI_NOT_FOUND The device path is not invalid.\r
93e3992d 67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
69 @retval EFI_SUCCESS The device path is retrieved and translated to\r
70 binary format.\r
71\r
72**/\r
93e3992d 73EFI_STATUS\r
74GetDevicePath (\r
75 IN EFI_STRING String,\r
ae79d2f9 76 OUT UINT8 **DevicePathData\r
93e3992d 77 )\r
78{\r
ae79d2f9
LG
79 UINTN Length;\r
80 EFI_STRING PathHdr;\r
81 UINT8 *DevicePathBuffer;\r
82 CHAR16 TemStr[2];\r
83 UINTN Index;\r
84 UINT8 DigitUint8;\r
85 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
86\r
87\r
88 if (String == NULL || DevicePathData == NULL) {\r
93e3992d 89 return EFI_INVALID_PARAMETER;\r
90 }\r
91\r
92 //\r
93 // Find the 'PATH=' of <PathHdr> and skip it.\r
94 //\r
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
96 if (*String == 0) {\r
97 return EFI_INVALID_PARAMETER;\r
98 }\r
ae79d2f9
LG
99 //\r
100 // Check whether path data does exist.\r
101 //\r
93e3992d 102 String += StrLen (L"PATH=");\r
ae79d2f9
LG
103 if (*String == 0) {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
93e3992d 106 PathHdr = String;\r
107\r
108 //\r
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
111 // of UEFI device path.\r
112 //\r
113 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
ae79d2f9
LG
114 //\r
115 // Check DevicePath Length\r
116 //\r
117 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
118 return EFI_NOT_FOUND;\r
93e3992d 119 }\r
ae79d2f9 120 \r
93e3992d 121 //\r
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
123 // as the device path resides in RAM memory.\r
124 // Translate the data into binary.\r
93e3992d 125 //\r
63d55bb9
LG
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
127 if (DevicePathBuffer == NULL) {\r
93e3992d 128 return EFI_OUT_OF_RESOURCES;\r
129 }\r
ae79d2f9
LG
130 \r
131 //\r
132 // Convert DevicePath\r
133 //\r
63d55bb9 134 ZeroMem (TemStr, sizeof (TemStr));\r
ae79d2f9
LG
135 for (Index = 0; Index < Length; Index ++) {\r
136 TemStr[0] = PathHdr[Index];\r
63d55bb9
LG
137 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
138 if ((Index & 1) == 0) {\r
139 DevicePathBuffer [Index/2] = DigitUint8;\r
140 } else {\r
141 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
142 }\r
143 }\r
63d55bb9 144 \r
ae79d2f9
LG
145 //\r
146 // Validate DevicePath\r
147 //\r
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;\r
149 while (!IsDevicePathEnd (DevicePath)) {\r
91a306ee 150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
ae79d2f9
LG
151 //\r
152 // Invalid device path\r
153 //\r
154 FreePool (DevicePathBuffer);\r
155 return EFI_NOT_FOUND;\r
156 }\r
157 DevicePath = NextDevicePathNode (DevicePath);\r
158 }\r
93e3992d 159\r
ae79d2f9
LG
160 //\r
161 // return the device path\r
162 //\r
163 *DevicePathData = DevicePathBuffer;\r
93e3992d 164 return EFI_SUCCESS;\r
93e3992d 165}\r
166\r
63d55bb9
LG
167/**\r
168 Converts the unicode character of the string from uppercase to lowercase.\r
169 This is a internal function.\r
170\r
aa75dfec 171 @param ConfigString String to be converted\r
63d55bb9
LG
172\r
173**/\r
174VOID\r
175EFIAPI\r
176HiiToLower (\r
84f9a9ec 177 IN EFI_STRING ConfigString\r
63d55bb9
LG
178 )\r
179{\r
84f9a9ec
LG
180 EFI_STRING String;\r
181 BOOLEAN Lower;\r
182\r
183 ASSERT (ConfigString != NULL);\r
184\r
185 //\r
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
187 //\r
188 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
189 if (*String == L'=') {\r
190 Lower = TRUE;\r
191 } else if (*String == L'&') {\r
192 Lower = FALSE;\r
193 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
194 *String = (CHAR16) (*String - L'A' + L'a');\r
63d55bb9
LG
195 }\r
196 }\r
84f9a9ec
LG
197\r
198 return;\r
63d55bb9 199}\r
93e3992d 200\r
93e3992d 201/**\r
202 Generate a sub string then output it.\r
203\r
e90b081a 204 This is a internal function.\r
205\r
93e3992d 206 @param String A constant string which is the prefix of the to be\r
207 generated string, e.g. GUID=\r
84f9a9ec 208\r
93e3992d 209 @param BufferLen The length of the Buffer in bytes.\r
84f9a9ec 210\r
813acf3a 211 @param Buffer Points to a buffer which will be converted to be the \r
84f9a9ec
LG
212 content of the generated string.\r
213\r
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
216 if 3, the buffer contains other data.\r
217\r
93e3992d 218 @param SubStr Points to the output string. It's caller's\r
219 responsibility to free this buffer.\r
220\r
221\r
222**/\r
93e3992d 223VOID\r
224GenerateSubStr (\r
225 IN CONST EFI_STRING String,\r
226 IN UINTN BufferLen,\r
813acf3a 227 IN VOID *Buffer,\r
228 IN UINT8 Flag,\r
93e3992d 229 OUT EFI_STRING *SubStr\r
230 )\r
231{\r
232 UINTN Length;\r
233 EFI_STRING Str;\r
813acf3a 234 EFI_STRING StringHeader;\r
63d55bb9
LG
235 CHAR16 *TemString;\r
236 CHAR16 *TemName;\r
237 UINT8 *TemBuffer;\r
238 UINTN Index;\r
93e3992d 239\r
240 ASSERT (String != NULL && SubStr != NULL);\r
241\r
242 if (Buffer == NULL) {\r
243 *SubStr = AllocateCopyPool (StrSize (String), String);\r
244 ASSERT (*SubStr != NULL);\r
245 return ;\r
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
358 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
359 if (Result == NULL) {\r
360 return EFI_OUT_OF_RESOURCES;\r
361 }\r
362\r
363 *(Result + Length - 1) = 0;\r
364 *ConfigBody = Result;\r
365 return EFI_SUCCESS;\r
93e3992d 366}\r
367\r
93e3992d 368/**\r
369 Append a string to a multi-string format.\r
370\r
e90b081a 371 This is a internal function.\r
372\r
93e3992d 373 @param MultiString String in <MultiConfigRequest>,\r
374 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
375 input, the buffer length of this string is\r
376 MAX_STRING_LENGTH. On output, the buffer length\r
377 might be updated.\r
378 @param AppendString NULL-terminated Unicode string.\r
379\r
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
382\r
383**/\r
93e3992d 384EFI_STATUS\r
385AppendToMultiString (\r
386 IN OUT EFI_STRING *MultiString,\r
387 IN EFI_STRING AppendString\r
388 )\r
389{\r
390 UINTN AppendStringSize;\r
391 UINTN MultiStringSize;\r
392\r
393 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
394 return EFI_INVALID_PARAMETER;\r
395 }\r
84f9a9ec
LG
396\r
397 AppendStringSize = StrSize (AppendString);\r
398 MultiStringSize = StrSize (*MultiString);\r
399\r
400 //\r
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
402 //\r
403 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
404 MultiStringSize > MAX_STRING_LENGTH) {\r
405 *MultiString = (EFI_STRING) ReallocatePool (\r
406 MultiStringSize,\r
407 MultiStringSize + AppendStringSize,\r
408 (VOID *) (*MultiString)\r
409 );\r
410 ASSERT (*MultiString != NULL);\r
411 }\r
412 //\r
413 // Append the incoming string\r
414 //\r
415 StrCat (*MultiString, AppendString);\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420\r
421/**\r
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
423 or WIDTH or VALUE.\r
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
425\r
426 This is a internal function.\r
427\r
428 @param StringPtr String in <BlockConfig> format and points to the\r
429 first character of <Number>.\r
430 @param Number The output value. Caller takes the responsibility\r
431 to free memory.\r
432 @param Len Length of the <Number>, in characters.\r
433\r
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
435 structures.\r
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
437 successfully.\r
438\r
439**/\r
440EFI_STATUS\r
441GetValueOfNumber (\r
442 IN EFI_STRING StringPtr,\r
443 OUT UINT8 **Number,\r
444 OUT UINTN *Len\r
445 )\r
446{\r
447 EFI_STRING TmpPtr;\r
448 UINTN Length;\r
449 EFI_STRING Str;\r
450 UINT8 *Buf;\r
451 EFI_STATUS Status;\r
452 UINT8 DigitUint8;\r
453 UINTN Index;\r
454 CHAR16 TemStr[2];\r
455\r
3a530010
ED
456 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {\r
457 return EFI_INVALID_PARAMETER;\r
458 }\r
84f9a9ec
LG
459\r
460 Buf = NULL;\r
461\r
462 TmpPtr = StringPtr;\r
463 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
464 StringPtr++;\r
465 }\r
466 *Len = StringPtr - TmpPtr;\r
467 Length = *Len + 1;\r
468\r
469 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
470 if (Str == NULL) {\r
471 Status = EFI_OUT_OF_RESOURCES;\r
472 goto Exit;\r
473 }\r
474 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
475 *(Str + *Len) = L'\0';\r
476\r
477 Length = (Length + 1) / 2;\r
478 Buf = (UINT8 *) AllocateZeroPool (Length);\r
479 if (Buf == NULL) {\r
480 Status = EFI_OUT_OF_RESOURCES;\r
481 goto Exit;\r
482 }\r
483 \r
484 Length = *Len;\r
485 ZeroMem (TemStr, sizeof (TemStr));\r
486 for (Index = 0; Index < Length; Index ++) {\r
487 TemStr[0] = Str[Length - Index - 1];\r
488 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
489 if ((Index & 1) == 0) {\r
490 Buf [Index/2] = DigitUint8;\r
491 } else {\r
492 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
493 }\r
494 }\r
495\r
496 *Number = Buf;\r
497 Status = EFI_SUCCESS;\r
498\r
499Exit:\r
500 if (Str != NULL) {\r
501 FreePool (Str);\r
502 }\r
503\r
504 return Status;\r
505}\r
506\r
507/**\r
508 This function merges DefaultAltCfgResp string into AltCfgResp string for\r
509 the missing AltCfgId in AltCfgResq.\r
510\r
511 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
512 <ConfigAltResp> format. The default value string \r
513 will be merged into it. \r
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
515 <MultiConfigAltResp> format. The default value \r
516 string may contain more than one ConfigAltResp\r
517 string for the different varstore buffer.\r
518\r
519 @retval EFI_SUCCESS The merged string returns.\r
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
521**/\r
522EFI_STATUS\r
523EFIAPI\r
524MergeDefaultString (\r
525 IN OUT EFI_STRING *AltCfgResp,\r
526 IN EFI_STRING DefaultAltCfgResp\r
527 )\r
528{\r
529 EFI_STRING StringPtrDefault;\r
530 EFI_STRING StringPtrEnd;\r
531 CHAR16 TempChar;\r
532 EFI_STRING StringPtr;\r
533 EFI_STRING AltConfigHdr;\r
534 UINTN HeaderLength;\r
535 UINTN SizeAltCfgResp;\r
536 \r
537 if (*AltCfgResp == NULL) {\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540 \r
541 //\r
542 // Get the requestr ConfigHdr\r
543 //\r
544 SizeAltCfgResp = 0;\r
545 StringPtr = *AltCfgResp;\r
546 \r
547 //\r
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
549 //\r
550 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
551 return EFI_INVALID_PARAMETER;\r
552 }\r
553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
554 StringPtr++;\r
555 }\r
556 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
557 StringPtr++;\r
558 }\r
559 if (*StringPtr == L'\0') {\r
560 return EFI_INVALID_PARAMETER;\r
561 }\r
562 StringPtr += StrLen (L"&PATH=");\r
563 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
564 StringPtr ++;\r
565 }\r
566 HeaderLength = StringPtr - *AltCfgResp;\r
567\r
568 //\r
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
571 //\r
572 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));\r
573 if (AltConfigHdr == NULL) {\r
574 return EFI_OUT_OF_RESOURCES;\r
575 }\r
576 StrCpy (AltConfigHdr, L"&");\r
577 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);\r
578 StrCat (AltConfigHdr, L"&ALTCFG=");\r
579 HeaderLength = StrLen (AltConfigHdr);\r
580 \r
581 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
582 while (StringPtrDefault != NULL) {\r
583 //\r
584 // Get AltCfg Name\r
585 //\r
586 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);\r
587 StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
588 \r
589 //\r
590 // Append the found default value string to the input AltCfgResp\r
591 // \r
592 if (StringPtr == NULL) {\r
593 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
594 SizeAltCfgResp = StrSize (*AltCfgResp);\r
595 if (StringPtrEnd == NULL) {\r
596 //\r
597 // No more default string is found.\r
598 //\r
599 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
600 SizeAltCfgResp,\r
601 SizeAltCfgResp + StrSize (StringPtrDefault),\r
602 (VOID *) (*AltCfgResp)\r
603 );\r
8567300a
LG
604 if (*AltCfgResp == NULL) {\r
605 FreePool (AltConfigHdr);\r
606 return EFI_OUT_OF_RESOURCES;\r
607 }\r
84f9a9ec
LG
608 StrCat (*AltCfgResp, StringPtrDefault);\r
609 break;\r
610 } else {\r
611 TempChar = *StringPtrEnd;\r
612 *StringPtrEnd = L'\0';\r
613 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
614 SizeAltCfgResp,\r
615 SizeAltCfgResp + StrSize (StringPtrDefault),\r
616 (VOID *) (*AltCfgResp)\r
617 );\r
6e3f5b2a
LG
618 if (*AltCfgResp == NULL) {\r
619 FreePool (AltConfigHdr);\r
620 return EFI_OUT_OF_RESOURCES;\r
621 }\r
84f9a9ec
LG
622 StrCat (*AltCfgResp, StringPtrDefault);\r
623 *StringPtrEnd = TempChar;\r
624 }\r
625 }\r
626 \r
627 //\r
628 // Find next AltCfg String\r
8567300a 629 //\r
84f9a9ec
LG
630 *(AltConfigHdr + HeaderLength) = L'\0';\r
631 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr); \r
632 }\r
8567300a
LG
633 \r
634 FreePool (AltConfigHdr);\r
84f9a9ec
LG
635 return EFI_SUCCESS; \r
636}\r
637\r
84f9a9ec
LG
638/**\r
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
640\r
641 @param BlockData The BlockData is updated to add new default value.\r
642 @param DefaultValueData The DefaultValue is added.\r
643\r
644**/\r
645VOID\r
646InsertDefaultValue (\r
647 IN IFR_BLOCK_DATA *BlockData,\r
648 IN IFR_DEFAULT_DATA *DefaultValueData\r
649 )\r
650{\r
651 LIST_ENTRY *Link;\r
652 IFR_DEFAULT_DATA *DefaultValueArray;\r
653\r
654 for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {\r
655 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
656 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
ef40f0f6
ED
657 //\r
658 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.\r
659 //\r
660 if (DefaultValueData->Type > DefaultValueArray->Type) {\r
6e3f5b2a
LG
661 //\r
662 // Update the default value array in BlockData.\r
663 //\r
e7fd76d1 664 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
ef40f0f6
ED
665 DefaultValueArray->Type = DefaultValueData->Type;\r
666 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;\r
6e3f5b2a 667 }\r
84f9a9ec 668 return;\r
ef40f0f6 669 } \r
84f9a9ec
LG
670 }\r
671\r
672 //\r
673 // Insert new default value data in tail.\r
674 //\r
ef40f0f6
ED
675 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
676 ASSERT (DefaultValueArray != NULL);\r
677 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));\r
678 InsertTailList (Link, &DefaultValueArray->Entry);\r
84f9a9ec
LG
679}\r
680\r
681/**\r
682 This function inserts new BlockData into the block link\r
683\r
684 @param BlockLink The list entry points to block array.\r
685 @param BlockData The point to BlockData is added.\r
686 \r
687**/\r
688VOID\r
689InsertBlockData (\r
690 IN LIST_ENTRY *BlockLink,\r
691 IN IFR_BLOCK_DATA **BlockData\r
692 )\r
693{\r
694 LIST_ENTRY *Link;\r
695 IFR_BLOCK_DATA *BlockArray;\r
696 IFR_BLOCK_DATA *BlockSingleData;\r
697\r
698 BlockSingleData = *BlockData;\r
699 \r
700 //\r
701 // Insert block data in its Offset and Width order.\r
702 //\r
703 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
704 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
705 if (BlockArray->Offset == BlockSingleData->Offset) {\r
706 if (BlockArray->Width > BlockSingleData->Width) {\r
707 //\r
708 // Insert this block data in the front of block array\r
709 //\r
710 InsertTailList (Link, &BlockSingleData->Entry);\r
711 return;\r
712 }\r
713\r
714 if (BlockArray->Width == BlockSingleData->Width) {\r
715 //\r
716 // The same block array has been added.\r
717 //\r
718 FreePool (BlockSingleData);\r
719 *BlockData = BlockArray;\r
720 return;\r
721 }\r
722 } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
723 //\r
724 // Insert new block data in the front of block array \r
725 //\r
726 InsertTailList (Link, &BlockSingleData->Entry);\r
727 return;\r
728 }\r
729 }\r
730 \r
731 //\r
732 // Add new block data into the tail.\r
733 //\r
734 InsertTailList (Link, &BlockSingleData->Entry);\r
735 return; \r
736}\r
737\r
738/**\r
739 This function checks VarOffset and VarWidth is in the block range.\r
740\r
aa75dfec 741 @param RequestBlockArray The block array is to be checked. \r
84f9a9ec
LG
742 @param VarOffset Offset of var to the structure\r
743 @param VarWidth Width of var.\r
744 \r
745 @retval TRUE This Var is in the block range.\r
746 @retval FALSE This Var is not in the block range.\r
747**/\r
748BOOLEAN\r
749BlockArrayCheck (\r
750 IN IFR_BLOCK_DATA *RequestBlockArray,\r
751 IN UINT16 VarOffset,\r
752 IN UINT16 VarWidth\r
753 )\r
754{\r
755 LIST_ENTRY *Link;\r
756 IFR_BLOCK_DATA *BlockData;\r
757 \r
758 //\r
759 // No Request Block array, all vars are got.\r
760 //\r
761 if (RequestBlockArray == NULL) {\r
762 return TRUE;\r
763 }\r
764 \r
765 //\r
766 // Check the input var is in the request block range.\r
767 //\r
768 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
769 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
770 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
771 return TRUE;\r
772 }\r
773 }\r
774\r
775 return FALSE;\r
776}\r
777\r
cce6230f
ED
778/**\r
779 Get form package data from data base.\r
780\r
781 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
782 @param HiiFormPackage The buffer saves the package data.\r
783 @param PackageSize The buffer size of the package data.\r
784\r
785**/\r
786EFI_STATUS\r
787GetFormPackageData (\r
788 IN HII_DATABASE_RECORD *DataBaseRecord,\r
789 IN OUT UINT8 **HiiFormPackage,\r
790 OUT UINTN *PackageSize\r
791 )\r
792{\r
793 EFI_STATUS Status;\r
794 UINTN Size;\r
795 UINTN ResultSize;\r
796\r
797 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {\r
798 return EFI_INVALID_PARAMETER;\r
799 }\r
800\r
801 Size = 0;\r
802 ResultSize = 0;\r
803 //\r
804 // 0. Get Hii Form Package by HiiHandle\r
805 //\r
806 Status = ExportFormPackages (\r
807 &mPrivate, \r
808 DataBaseRecord->Handle, \r
809 DataBaseRecord->PackageList, \r
810 0, \r
811 Size, \r
812 HiiFormPackage,\r
813 &ResultSize\r
814 );\r
815 if (EFI_ERROR (Status)) {\r
816 return Status;\r
817 }\r
818 \r
819 (*HiiFormPackage) = AllocatePool (ResultSize);\r
820 if (*HiiFormPackage == NULL) {\r
821 Status = EFI_OUT_OF_RESOURCES;\r
822 return Status;\r
823 }\r
824\r
825 //\r
826 // Get HiiFormPackage by HiiHandle\r
827 //\r
828 Size = ResultSize;\r
829 ResultSize = 0;\r
830 Status = ExportFormPackages (\r
831 &mPrivate, \r
832 DataBaseRecord->Handle, \r
833 DataBaseRecord->PackageList, \r
834 0,\r
835 Size, \r
836 *HiiFormPackage,\r
837 &ResultSize\r
838 );\r
839 if (EFI_ERROR (Status)) {\r
840 FreePool (*HiiFormPackage);\r
841 }\r
842 \r
843 *PackageSize = Size;\r
844\r
845 return Status;\r
846}\r
847\r
848\r
849/**\r
850 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
851\r
852 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
853 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
854 the first found varstore will be as ConfigHdr.\r
855 @param IsEfiVarstore Whether the request storage type is efi varstore type.\r
856 @param EfiVarStore The efi varstore info which will return.\r
857**/ \r
858EFI_STATUS\r
859GetVarStoreType (\r
860 IN HII_DATABASE_RECORD *DataBaseRecord,\r
861 IN EFI_STRING ConfigHdr,\r
862 OUT BOOLEAN *IsEfiVarstore,\r
863 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore\r
864 \r
865 )\r
866{\r
867 EFI_STATUS Status;\r
868 UINTN IfrOffset;\r
869 EFI_IFR_OP_HEADER *IfrOpHdr;\r
870 CHAR16 *VarStoreName;\r
871 EFI_STRING GuidStr;\r
872 EFI_STRING NameStr;\r
873 EFI_STRING TempStr;\r
874 UINTN LengthString; \r
875 UINT8 *HiiFormPackage;\r
876 UINTN PackageSize;\r
877 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
878 \r
879 HiiFormPackage = NULL;\r
880 LengthString = 0;\r
881 Status = EFI_SUCCESS;\r
882 GuidStr = NULL;\r
883 NameStr = NULL;\r
884 TempStr = NULL;\r
885\r
886 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);\r
887 if (EFI_ERROR (Status)) {\r
888 return Status;\r
889 }\r
890\r
891 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
892 while (IfrOffset < PackageSize) {\r
893 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset); \r
894 IfrOffset += IfrOpHdr->Length;\r
895\r
896 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {\r
897 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
898 //\r
899 // If the length is small than the structure, this is from old efi \r
900 // varstore definition. Old efi varstore get config directly from \r
901 // GetVariable function.\r
902 //\r
903 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
904 continue;\r
905 }\r
906\r
907 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
908 if (VarStoreName == NULL) {\r
909 Status = EFI_OUT_OF_RESOURCES;\r
910 goto Done;\r
911 }\r
912 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);\r
913\r
914 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);\r
915 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
916 LengthString = StrLen (GuidStr);\r
917 LengthString = LengthString + StrLen (NameStr) + 1;\r
918 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
919 if (TempStr == NULL) {\r
920 FreePool (GuidStr);\r
921 FreePool (NameStr);\r
922 FreePool (VarStoreName);\r
923 Status = EFI_OUT_OF_RESOURCES;\r
924 goto Done;\r
925 }\r
926 StrCpy (TempStr, GuidStr);\r
927 StrCat (TempStr, NameStr);\r
928 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
929 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);\r
930 if (*EfiVarStore == NULL) {\r
931 FreePool (VarStoreName);\r
932 FreePool (GuidStr);\r
933 FreePool (NameStr);\r
934 FreePool (TempStr);\r
935 Status = EFI_OUT_OF_RESOURCES;\r
936 goto Done;\r
937 }\r
938 *IsEfiVarstore = TRUE;\r
939 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);\r
940 } \r
941 \r
942 //\r
943 // Free alllocated temp string.\r
944 //\r
945 FreePool (VarStoreName);\r
946 FreePool (GuidStr);\r
947 FreePool (NameStr);\r
948 FreePool (TempStr);\r
949 }\r
950 }\r
951Done:\r
952 if (HiiFormPackage != NULL) {\r
953 FreePool (HiiFormPackage);\r
954 }\r
955\r
956 return Status;\r
957}\r
958\r
84f9a9ec
LG
959/**\r
960 This function parses Form Package to get the block array and the default\r
961 value array according to the request ConfigHdr.\r
962\r
963 @param Package Pointer to the form package data.\r
964 @param PackageLength Length of the pacakge.\r
965 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
966 the first found varstore will be as ConfigHdr.\r
967 @param RequestBlockArray The block array is retrieved from the request string.\r
968 @param VarStorageData VarStorage structure contains the got block and default value.\r
969 @param PIfrDefaultIdArray Point to the got default id and default name array.\r
970\r
971 @retval EFI_SUCCESS The block array and the default value array are got.\r
972 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
973 are conflicted. \r
974 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
975**/\r
976EFI_STATUS\r
977EFIAPI\r
978ParseIfrData (\r
979 IN UINT8 *Package,\r
aa75dfec 980 IN UINT32 PackageLength,\r
84f9a9ec
LG
981 IN EFI_STRING ConfigHdr,\r
982 IN IFR_BLOCK_DATA *RequestBlockArray,\r
983 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
8567300a 984 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
84f9a9ec
LG
985 )\r
986{\r
987 EFI_STATUS Status;\r
988 UINTN IfrOffset;\r
989 EFI_IFR_VARSTORE *IfrVarStore;\r
cce6230f 990 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
84f9a9ec
LG
991 EFI_IFR_OP_HEADER *IfrOpHdr;\r
992 EFI_IFR_ONE_OF *IfrOneOf;\r
e7fd76d1 993 EFI_IFR_REF4 *IfrRef;\r
84f9a9ec
LG
994 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
995 EFI_IFR_DEFAULT *IfrDefault;\r
996 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
997 EFI_IFR_CHECKBOX *IfrCheckBox;\r
998 EFI_IFR_PASSWORD *IfrPassword;\r
999 EFI_IFR_STRING *IfrString;\r
d9bbabfd
ED
1000 EFI_IFR_DATE *IfrDate;\r
1001 EFI_IFR_TIME *IfrTime;\r
ef40f0f6
ED
1002 IFR_DEFAULT_DATA DefaultData;\r
1003 IFR_DEFAULT_DATA *DefaultDataPtr;\r
84f9a9ec
LG
1004 IFR_BLOCK_DATA *BlockData;\r
1005 CHAR16 *VarStoreName;\r
1006 UINT16 VarOffset;\r
1007 UINT16 VarWidth;\r
84f9a9ec
LG
1008 UINT16 VarDefaultId;\r
1009 EFI_STRING GuidStr;\r
1010 EFI_STRING NameStr;\r
1011 EFI_STRING TempStr;\r
1012 UINTN LengthString;\r
cf4c5a42 1013 BOOLEAN FirstOneOfOption;\r
ef40f0f6
ED
1014 LIST_ENTRY *LinkData;\r
1015 LIST_ENTRY *LinkDefault;\r
84f9a9ec 1016\r
84f9a9ec
LG
1017 LengthString = 0;\r
1018 Status = EFI_SUCCESS;\r
1019 GuidStr = NULL;\r
1020 NameStr = NULL;\r
1021 TempStr = NULL;\r
1022 BlockData = NULL;\r
ef40f0f6 1023 DefaultDataPtr = NULL;\r
cf4c5a42 1024 FirstOneOfOption = FALSE;\r
ef40f0f6 1025 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
84f9a9ec
LG
1026\r
1027 //\r
1028 // Go through the form package to parse OpCode one by one.\r
1029 //\r
1030 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
aa75dfec 1031 while (IfrOffset < PackageLength) {\r
84f9a9ec
LG
1032 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
1033\r
1034 switch (IfrOpHdr->OpCode) {\r
1035 case EFI_IFR_VARSTORE_OP:\r
1036 //\r
1037 // VarStore is found. Don't need to search any more.\r
1038 //\r
1039 if (VarStorageData->Size != 0) {\r
1040 break;\r
1041 }\r
1042\r
1043 //\r
1044 // Get the requied varstore information\r
1045 // Add varstore by Guid and Name in ConfigHdr\r
1046 // Make sure Offset is in varstore size and varstoreid\r
1047 //\r
1048 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
1049 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
1050 if (VarStoreName == NULL) {\r
1051 Status = EFI_OUT_OF_RESOURCES;\r
1052 goto Done;\r
1053 }\r
1054 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);\r
1055\r
1056 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);\r
1057 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
1058 LengthString = StrLen (GuidStr);\r
1059 LengthString = LengthString + StrLen (NameStr) + 1;\r
1060 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
cce6230f 1061 if (TempStr == NULL) {\r
04da0b4a
LG
1062 FreePool (GuidStr);\r
1063 FreePool (NameStr);\r
1f1cb2f2 1064 FreePool (VarStoreName);\r
84f9a9ec
LG
1065 Status = EFI_OUT_OF_RESOURCES;\r
1066 goto Done;\r
1067 }\r
1068 StrCpy (TempStr, GuidStr);\r
1069 StrCat (TempStr, NameStr);\r
1070 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1071 //\r
1072 // Find the matched VarStore\r
1073 //\r
1074 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
1075 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
1076 VarStorageData->Size = IfrVarStore->Size;\r
1077 VarStorageData->Name = VarStoreName;\r
1078 } else {\r
1079 //\r
1080 // No found, free the allocated memory \r
1081 //\r
1082 FreePool (VarStoreName);\r
1083 }\r
1084 //\r
1085 // Free alllocated temp string.\r
1086 //\r
04da0b4a
LG
1087 FreePool (GuidStr);\r
1088 FreePool (NameStr);\r
84f9a9ec 1089 FreePool (TempStr);\r
84f9a9ec
LG
1090 break;\r
1091\r
cce6230f
ED
1092 case EFI_IFR_VARSTORE_EFI_OP:\r
1093 //\r
1094 // VarStore is found. Don't need to search any more.\r
1095 //\r
1096 if (VarStorageData->Size != 0) {\r
1097 break;\r
1098 }\r
1099\r
1100 //\r
1101 // Get the requied varstore information\r
1102 // Add varstore by Guid and Name in ConfigHdr\r
1103 // Make sure Offset is in varstore size and varstoreid\r
1104 //\r
1105 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1106\r
1107 //\r
1108 // If the length is small than the structure, this is from old efi \r
1109 // varstore definition. Old efi varstore get config directly from \r
1110 // GetVariable function.\r
1111 // \r
1112 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1113 break;\r
1114 }\r
1115\r
1116 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
1117 if (VarStoreName == NULL) {\r
1118 Status = EFI_OUT_OF_RESOURCES;\r
1119 goto Done;\r
1120 }\r
1121 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);\r
1122\r
1123 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);\r
1124 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
1125 LengthString = StrLen (GuidStr);\r
1126 LengthString = LengthString + StrLen (NameStr) + 1;\r
1127 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1128 if (TempStr == NULL) {\r
1129 FreePool (GuidStr);\r
1130 FreePool (NameStr);\r
1131 FreePool (VarStoreName);\r
1132 Status = EFI_OUT_OF_RESOURCES;\r
1133 goto Done;\r
1134 }\r
1135 StrCpy (TempStr, GuidStr);\r
1136 StrCat (TempStr, NameStr);\r
1137 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1138 //\r
1139 // Find the matched VarStore\r
1140 //\r
1141 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
1142 VarStorageData->VarStoreId = IfrEfiVarStore->VarStoreId;\r
1143 VarStorageData->Size = IfrEfiVarStore->Size;\r
1144 VarStorageData->Name = VarStoreName;\r
1145 } else {\r
1146 //\r
1147 // No found, free the allocated memory \r
1148 //\r
1149 FreePool (VarStoreName);\r
1150 }\r
1151 //\r
1152 // Free alllocated temp string.\r
1153 //\r
1154 FreePool (GuidStr);\r
1155 FreePool (NameStr);\r
1156 FreePool (TempStr);\r
1157 break;\r
1158\r
84f9a9ec
LG
1159 case EFI_IFR_DEFAULTSTORE_OP:\r
1160 //\r
1161 // Add new the map between default id and default name.\r
1162 //\r
ef40f0f6
ED
1163 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1164 if (DefaultDataPtr == NULL) {\r
84f9a9ec
LG
1165 Status = EFI_OUT_OF_RESOURCES;\r
1166 goto Done;\r
1167 }\r
ef40f0f6
ED
1168 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
1169 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
1170 DefaultDataPtr = NULL;\r
84f9a9ec
LG
1171 break;\r
1172\r
1173 case EFI_IFR_FORM_OP:\r
2573712e 1174 case EFI_IFR_FORM_MAP_OP:\r
84f9a9ec
LG
1175 //\r
1176 // No matched varstore is found and directly return.\r
1177 //\r
1178 if (VarStorageData->Size == 0) {\r
1179 Status = EFI_SUCCESS;\r
1180 goto Done;\r
1181 }\r
1182 break;\r
1183\r
e7fd76d1
ED
1184 case EFI_IFR_REF_OP:\r
1185 //\r
1186 // Ref question is not in IFR Form. This IFR form is not valid. \r
1187 //\r
1188 if (VarStorageData->Size == 0) {\r
1189 Status = EFI_INVALID_PARAMETER;\r
1190 goto Done;\r
1191 }\r
1192 //\r
1193 // Check whether this question is for the requested varstore.\r
1194 //\r
1195 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
1196 if (IfrRef->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1197 break;\r
1198 }\r
1199 \r
1200 //\r
1201 // Get Offset/Width by Question header.\r
1202 //\r
1203 VarOffset = IfrRef->Question.VarStoreInfo.VarOffset;\r
1204 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
1205 //\r
1206 // Check whether this question is in requested block array.\r
1207 //\r
1208 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1209 //\r
1210 // This question is not in the requested string. Skip it.\r
1211 //\r
1212 break;\r
1213 }\r
1214\r
1215 //\r
1216 // Check this var question is in the var storage \r
1217 //\r
1218 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1219 Status = EFI_INVALID_PARAMETER;\r
1220 goto Done;\r
1221 }\r
1222 \r
1223 //\r
1224 // Set Block Data\r
1225 //\r
1226 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1227 if (BlockData == NULL) {\r
1228 Status = EFI_OUT_OF_RESOURCES;\r
1229 goto Done;\r
1230 }\r
1231 BlockData->Offset = VarOffset;\r
1232 BlockData->Width = VarWidth;\r
1233 BlockData->QuestionId = IfrRef->Question.QuestionId;\r
1234 BlockData->OpCode = IfrOpHdr->OpCode;\r
1235 BlockData->Scope = IfrOpHdr->Scope;\r
1236 InitializeListHead (&BlockData->DefaultValueEntry);\r
1237 //\r
1238 // Add Block Data into VarStorageData BlockEntry\r
1239 //\r
1240 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1241 break;\r
1242\r
84f9a9ec
LG
1243 case EFI_IFR_ONE_OF_OP:\r
1244 case EFI_IFR_NUMERIC_OP:\r
1245 //\r
1246 // Numeric and OneOf has the same opcode structure.\r
1247 //\r
1248\r
8567300a
LG
1249 //\r
1250 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
1251 //\r
1252 if (VarStorageData->Size == 0) {\r
1253 Status = EFI_INVALID_PARAMETER;\r
1254 goto Done;\r
1255 }\r
84f9a9ec
LG
1256 //\r
1257 // Check whether this question is for the requested varstore.\r
1258 //\r
1259 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1260 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1261 break;\r
1262 }\r
1263 \r
1264 //\r
1265 // Get Offset/Width by Question header and OneOf Flags\r
1266 //\r
1267 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
1268 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
1269 //\r
1270 // Check whether this question is in requested block array.\r
1271 //\r
1272 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1273 //\r
1274 // This question is not in the requested string. Skip it.\r
1275 //\r
1276 break;\r
1277 }\r
1278\r
1279 //\r
1280 // Check this var question is in the var storage \r
1281 //\r
1282 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1283 Status = EFI_INVALID_PARAMETER;\r
1284 goto Done;\r
1285 }\r
1286 \r
1287 //\r
1288 // Set Block Data\r
1289 //\r
1290 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1291 if (BlockData == NULL) {\r
1292 Status = EFI_OUT_OF_RESOURCES;\r
1293 goto Done;\r
1294 }\r
1295 BlockData->Offset = VarOffset;\r
1296 BlockData->Width = VarWidth;\r
1297 BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
1298 BlockData->OpCode = IfrOpHdr->OpCode;\r
1299 BlockData->Scope = IfrOpHdr->Scope;\r
1300 InitializeListHead (&BlockData->DefaultValueEntry);\r
1301 //\r
1302 // Add Block Data into VarStorageData BlockEntry\r
1303 //\r
1304 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
cf4c5a42
LG
1305 \r
1306 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
1307 //\r
1308 // Set this flag to TRUE for the first oneof option.\r
1309 //\r
1310 FirstOneOfOption = TRUE;\r
1311 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
1312 //\r
1313 // Numeric minimum value will be used as default value when no default is specified. \r
1314 //\r
eb5e7d3e 1315 DefaultData.Type = DefaultValueFromDefault;\r
cf4c5a42
LG
1316 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1317 case EFI_IFR_NUMERIC_SIZE_1:\r
e7fd76d1 1318 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
cf4c5a42
LG
1319 break;\r
1320 \r
1321 case EFI_IFR_NUMERIC_SIZE_2:\r
e7fd76d1 1322 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
cf4c5a42
LG
1323 break;\r
1324 \r
1325 case EFI_IFR_NUMERIC_SIZE_4:\r
e7fd76d1 1326 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
cf4c5a42
LG
1327 break;\r
1328 \r
1329 case EFI_IFR_NUMERIC_SIZE_8:\r
e7fd76d1 1330 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
cf4c5a42
LG
1331 break;\r
1332 }\r
1333 //\r
ef40f0f6
ED
1334 // Set default value base on the DefaultId list get from IFR data.\r
1335 // \r
1336 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
1337 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
1338 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1339 InsertDefaultValue (BlockData, &DefaultData);\r
1340 }\r
cf4c5a42 1341 }\r
84f9a9ec
LG
1342 break;\r
1343\r
1344 case EFI_IFR_ORDERED_LIST_OP:\r
1345 //\r
1346 // offset by question header\r
1347 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1348 // no default value and default id, how to define its default value?\r
1349 //\r
8567300a
LG
1350\r
1351 //\r
1352 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1353 //\r
1354 if (VarStorageData->Size == 0) {\r
1355 Status = EFI_INVALID_PARAMETER;\r
1356 goto Done;\r
1357 }\r
84f9a9ec
LG
1358 //\r
1359 // Check whether this question is for the requested varstore.\r
1360 //\r
1361 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1362 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
ff28420b 1363 BlockData = NULL;\r
84f9a9ec
LG
1364 break;\r
1365 }\r
ff28420b 1366\r
84f9a9ec
LG
1367 //\r
1368 // Get Offset/Width by Question header and OneOf Flags\r
1369 //\r
1370 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
1371 VarWidth = IfrOrderedList->MaxContainers;\r
84f9a9ec
LG
1372 \r
1373 //\r
1374 // Set Block Data\r
1375 //\r
1376 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1377 if (BlockData == NULL) {\r
1378 Status = EFI_OUT_OF_RESOURCES;\r
1379 goto Done;\r
1380 }\r
1381 BlockData->Offset = VarOffset;\r
1382 BlockData->Width = VarWidth;\r
1383 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
1384 BlockData->OpCode = IfrOpHdr->OpCode;\r
1385 BlockData->Scope = IfrOpHdr->Scope;\r
1386 InitializeListHead (&BlockData->DefaultValueEntry);\r
84f9a9ec
LG
1387 break;\r
1388\r
1389 case EFI_IFR_CHECKBOX_OP:\r
1390 //\r
1391 // EFI_IFR_DEFAULT_OP\r
1392 // offset by question header\r
1393 // width is 1 sizeof (BOOLEAN)\r
1394 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1395 // value by DefaultOption\r
1396 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1397 // \r
1398\r
8567300a
LG
1399 //\r
1400 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1401 //\r
1402 if (VarStorageData->Size == 0) {\r
1403 Status = EFI_INVALID_PARAMETER;\r
1404 goto Done;\r
1405 }\r
84f9a9ec
LG
1406 //\r
1407 // Check whether this question is for the requested varstore.\r
1408 //\r
1409 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1410 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1411 break;\r
1412 }\r
1413 \r
1414 //\r
1415 // Get Offset/Width by Question header and OneOf Flags\r
1416 //\r
1417 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
c9325700 1418 VarWidth = (UINT16) sizeof (BOOLEAN);\r
84f9a9ec
LG
1419\r
1420 //\r
1421 // Check whether this question is in requested block array.\r
1422 //\r
1423 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1424 //\r
1425 // This question is not in the requested string. Skip it.\r
1426 //\r
1427 break;\r
1428 }\r
1429\r
1430 //\r
1431 // Check this var question is in the var storage \r
1432 //\r
1433 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1434 Status = EFI_INVALID_PARAMETER;\r
1435 goto Done;\r
1436 }\r
1437 \r
1438 //\r
1439 // Set Block Data\r
1440 //\r
1441 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1442 if (BlockData == NULL) {\r
1443 Status = EFI_OUT_OF_RESOURCES;\r
1444 goto Done;\r
1445 }\r
1446 BlockData->Offset = VarOffset;\r
1447 BlockData->Width = VarWidth;\r
1448 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
1449 BlockData->OpCode = IfrOpHdr->OpCode;\r
1450 BlockData->Scope = IfrOpHdr->Scope;\r
1451 InitializeListHead (&BlockData->DefaultValueEntry);\r
1452 //\r
1453 // Add Block Data into VarStorageData BlockEntry\r
1454 //\r
1455 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1456 \r
1457 //\r
e9668a60 1458 // Add default value for standard ID by CheckBox Flag\r
84f9a9ec 1459 //\r
e9668a60
LG
1460 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1461 //\r
1462 // Prepare new DefaultValue\r
1463 //\r
ef40f0f6 1464 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1465 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1466 //\r
e9668a60 1467 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1468 //\r
e7fd76d1
ED
1469 DefaultData.Type = DefaultValueFromFlag;\r
1470 DefaultData.Value.b = TRUE;\r
e9668a60 1471 } else {\r
84f9a9ec 1472 //\r
e9668a60 1473 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1474 //\r
e7fd76d1
ED
1475 DefaultData.Type = DefaultValueFromDefault;\r
1476 DefaultData.Value.b = FALSE;\r
84f9a9ec 1477 }\r
e9668a60
LG
1478 //\r
1479 // Add DefaultValue into current BlockData\r
1480 //\r
ef40f0f6 1481 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 1482\r
e9668a60
LG
1483 //\r
1484 // Add default value for Manufacture ID by CheckBox Flag\r
1485 //\r
1486 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1487 //\r
1488 // Prepare new DefaultValue\r
1489 //\r
ef40f0f6 1490 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
1491 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1492 //\r
e9668a60 1493 // When flag is set, defautl value is TRUE.\r
84f9a9ec 1494 //\r
e7fd76d1
ED
1495 DefaultData.Type = DefaultValueFromFlag;\r
1496 DefaultData.Value.b = TRUE;\r
e9668a60 1497 } else {\r
84f9a9ec 1498 //\r
e9668a60 1499 // When flag is not set, defautl value is FASLE.\r
84f9a9ec 1500 //\r
e7fd76d1
ED
1501 DefaultData.Type = DefaultValueFromDefault; \r
1502 DefaultData.Value.b = FALSE;\r
84f9a9ec 1503 }\r
e9668a60
LG
1504 //\r
1505 // Add DefaultValue into current BlockData\r
1506 //\r
ef40f0f6 1507 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec
LG
1508 break;\r
1509\r
d9bbabfd
ED
1510 case EFI_IFR_DATE_OP:\r
1511 //\r
1512 // offset by question header\r
1513 // width MaxSize * sizeof (CHAR16)\r
1514 // no default value, only block array\r
1515 //\r
1516\r
1517 //\r
1518 // Date question is not in IFR Form. This IFR form is not valid. \r
1519 //\r
1520 if (VarStorageData->Size == 0) {\r
1521 Status = EFI_INVALID_PARAMETER;\r
1522 goto Done;\r
1523 }\r
1524 //\r
1525 // Check whether this question is for the requested varstore.\r
1526 //\r
1527 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
1528 if (IfrDate->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1529 break;\r
1530 }\r
1531\r
1532 //\r
1533 // Get Offset/Width by Question header and OneOf Flags\r
1534 //\r
1535 VarOffset = IfrDate->Question.VarStoreInfo.VarOffset;\r
1536 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
1537\r
1538 //\r
1539 // Check whether this question is in requested block array.\r
1540 //\r
1541 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1542 //\r
1543 // This question is not in the requested array. Skip it.\r
1544 //\r
1545 break;\r
1546 }\r
1547\r
1548 //\r
1549 // Check this var question is in the var storage \r
1550 //\r
1551 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1552 Status = EFI_INVALID_PARAMETER;\r
1553 goto Done;\r
1554 }\r
1555\r
1556 //\r
1557 // Set Block Data\r
1558 //\r
1559 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1560 if (BlockData == NULL) {\r
1561 Status = EFI_OUT_OF_RESOURCES;\r
1562 goto Done;\r
1563 }\r
1564 BlockData->Offset = VarOffset;\r
1565 BlockData->Width = VarWidth;\r
1566 BlockData->QuestionId = IfrDate->Question.QuestionId;\r
1567 BlockData->OpCode = IfrOpHdr->OpCode;\r
1568 BlockData->Scope = IfrOpHdr->Scope;\r
1569 InitializeListHead (&BlockData->DefaultValueEntry);\r
1570\r
1571 //\r
1572 // Add Block Data into VarStorageData BlockEntry\r
1573 //\r
1574 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1575 break;\r
1576\r
1577 case EFI_IFR_TIME_OP:\r
1578 //\r
1579 // offset by question header\r
1580 // width MaxSize * sizeof (CHAR16)\r
1581 // no default value, only block array\r
1582 //\r
1583\r
1584 //\r
1585 // Time question is not in IFR Form. This IFR form is not valid. \r
1586 //\r
1587 if (VarStorageData->Size == 0) {\r
1588 Status = EFI_INVALID_PARAMETER;\r
1589 goto Done;\r
1590 }\r
1591 //\r
1592 // Check whether this question is for the requested varstore.\r
1593 //\r
1594 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
1595 if (IfrTime->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1596 break;\r
1597 }\r
1598\r
1599 //\r
1600 // Get Offset/Width by Question header and OneOf Flags\r
1601 //\r
1602 VarOffset = IfrTime->Question.VarStoreInfo.VarOffset;\r
1603 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
1604\r
1605 //\r
1606 // Check whether this question is in requested block array.\r
1607 //\r
1608 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1609 //\r
1610 // This question is not in the requested array. Skip it.\r
1611 //\r
1612 break;\r
1613 }\r
1614\r
1615 //\r
1616 // Check this var question is in the var storage \r
1617 //\r
1618 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1619 Status = EFI_INVALID_PARAMETER;\r
1620 goto Done;\r
1621 }\r
1622\r
1623 //\r
1624 // Set Block Data\r
1625 //\r
1626 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1627 if (BlockData == NULL) {\r
1628 Status = EFI_OUT_OF_RESOURCES;\r
1629 goto Done;\r
1630 }\r
1631 BlockData->Offset = VarOffset;\r
1632 BlockData->Width = VarWidth;\r
1633 BlockData->QuestionId = IfrTime->Question.QuestionId;\r
1634 BlockData->OpCode = IfrOpHdr->OpCode;\r
1635 BlockData->Scope = IfrOpHdr->Scope;\r
1636 InitializeListHead (&BlockData->DefaultValueEntry);\r
1637\r
1638 //\r
1639 // Add Block Data into VarStorageData BlockEntry\r
1640 //\r
1641 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1642 break;\r
1643\r
84f9a9ec
LG
1644 case EFI_IFR_STRING_OP:\r
1645 //\r
1646 // offset by question header\r
1647 // width MaxSize * sizeof (CHAR16)\r
1648 // no default value, only block array\r
1649 //\r
1650\r
8567300a
LG
1651 //\r
1652 // String question is not in IFR Form. This IFR form is not valid. \r
1653 //\r
1654 if (VarStorageData->Size == 0) {\r
1655 Status = EFI_INVALID_PARAMETER;\r
1656 goto Done;\r
1657 }\r
84f9a9ec
LG
1658 //\r
1659 // Check whether this question is for the requested varstore.\r
1660 //\r
1661 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1662 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1663 break;\r
1664 }\r
1665 \r
1666 //\r
1667 // Get Offset/Width by Question header and OneOf Flags\r
1668 //\r
1669 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
1670 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1671\r
1672 //\r
1673 // Check whether this question is in requested block array.\r
1674 //\r
1675 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1676 //\r
1677 // This question is not in the requested string. Skip it.\r
1678 //\r
1679 break;\r
1680 }\r
1681\r
1682 //\r
1683 // Check this var question is in the var storage \r
1684 //\r
1685 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1686 Status = EFI_INVALID_PARAMETER;\r
1687 goto Done;\r
1688 }\r
1689 \r
1690 //\r
1691 // Set Block Data\r
1692 //\r
1693 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1694 if (BlockData == NULL) {\r
1695 Status = EFI_OUT_OF_RESOURCES;\r
1696 goto Done;\r
1697 }\r
1698 BlockData->Offset = VarOffset;\r
1699 BlockData->Width = VarWidth;\r
1700 BlockData->QuestionId = IfrString->Question.QuestionId;\r
1701 BlockData->OpCode = IfrOpHdr->OpCode;\r
1702 InitializeListHead (&BlockData->DefaultValueEntry);\r
1703 \r
1704 //\r
1705 // Add Block Data into VarStorageData BlockEntry\r
1706 //\r
1707 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1708 \r
1709 //\r
1710 // No default value for string.\r
1711 //\r
1712 BlockData = NULL;\r
1713 break;\r
1714\r
1715 case EFI_IFR_PASSWORD_OP:\r
1716 //\r
1717 // offset by question header\r
1718 // width MaxSize * sizeof (CHAR16)\r
1719 // no default value, only block array\r
1720 //\r
1721\r
8567300a
LG
1722 //\r
1723 // Password question is not in IFR Form. This IFR form is not valid. \r
1724 //\r
1725 if (VarStorageData->Size == 0) {\r
1726 Status = EFI_INVALID_PARAMETER;\r
1727 goto Done;\r
1728 }\r
84f9a9ec
LG
1729 //\r
1730 // Check whether this question is for the requested varstore.\r
1731 //\r
1732 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1733 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1734 break;\r
1735 }\r
1736 \r
1737 //\r
1738 // Get Offset/Width by Question header and OneOf Flags\r
1739 //\r
1740 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
1741 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1742\r
1743 //\r
1744 // Check whether this question is in requested block array.\r
1745 //\r
1746 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1747 //\r
1748 // This question is not in the requested string. Skip it.\r
1749 //\r
1750 break;\r
1751 }\r
1752\r
1753 //\r
1754 // Check this var question is in the var storage \r
1755 //\r
1756 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1757 Status = EFI_INVALID_PARAMETER;\r
1758 goto Done;\r
1759 }\r
1760 \r
1761 //\r
1762 // Set Block Data\r
1763 //\r
1764 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1765 if (BlockData == NULL) {\r
1766 Status = EFI_OUT_OF_RESOURCES;\r
1767 goto Done;\r
1768 }\r
1769 BlockData->Offset = VarOffset;\r
1770 BlockData->Width = VarWidth;\r
1771 BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
1772 BlockData->OpCode = IfrOpHdr->OpCode;\r
1773 InitializeListHead (&BlockData->DefaultValueEntry);\r
1774 \r
1775 //\r
1776 // Add Block Data into VarStorageData BlockEntry\r
1777 //\r
1778 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1779 \r
1780 //\r
1781 // No default value for string.\r
1782 //\r
1783 BlockData = NULL;\r
1784 break;\r
1785\r
1786 case EFI_IFR_ONE_OF_OPTION_OP:\r
1787 //\r
1788 // No matched block data is ignored.\r
1789 //\r
1790 if (BlockData == NULL || BlockData->Scope == 0) {\r
1791 break;\r
1792 }\r
1793 \r
1794 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1795 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1796 //\r
1797 // Get ordered list option data type.\r
1798 //\r
1799 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1800 VarWidth = 1;\r
1801 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1802 VarWidth = 2;\r
1803 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1804 VarWidth = 4;\r
1805 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1806 VarWidth = 8;\r
1807 } else {\r
1808 //\r
1809 // Invalid ordered list option data type.\r
1810 //\r
1811 Status = EFI_INVALID_PARAMETER;\r
ff28420b 1812 FreePool (BlockData);\r
84f9a9ec
LG
1813 goto Done;\r
1814 }\r
ff28420b 1815\r
84f9a9ec
LG
1816 //\r
1817 // Calculate Ordered list QuestionId width.\r
1818 //\r
1819 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
ff28420b
LG
1820 //\r
1821 // Check whether this question is in requested block array.\r
1822 //\r
1823 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width)) {\r
1824 //\r
1825 // This question is not in the requested string. Skip it.\r
1826 //\r
1827 FreePool (BlockData);\r
1828 BlockData = NULL;\r
1829 break;\r
1830 }\r
1831 //\r
1832 // Check this var question is in the var storage \r
1833 //\r
1834 if ((BlockData->Offset + BlockData->Width) > VarStorageData->Size) {\r
1835 Status = EFI_INVALID_PARAMETER;\r
1836 FreePool (BlockData);\r
1837 goto Done;\r
1838 }\r
1839 //\r
1840 // Add Block Data into VarStorageData BlockEntry\r
1841 //\r
1842 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1843 //\r
1844 // No default data for OrderedList.\r
1845 //\r
84f9a9ec
LG
1846 BlockData = NULL;\r
1847 break;\r
1848 }\r
1849\r
ef40f0f6
ED
1850 //\r
1851 // 1. Set default value for OneOf option when flag field has default attribute.\r
1852 //\r
cf4c5a42 1853 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
ef40f0f6 1854 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
cf4c5a42
LG
1855 //\r
1856 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
1857 // The first oneof option value will be used as default value when no default value is specified. \r
1858 //\r
1859 FirstOneOfOption = FALSE;\r
ef40f0f6 1860 \r
84f9a9ec
LG
1861 // Prepare new DefaultValue\r
1862 //\r
eb5e7d3e 1863 DefaultData.Type = DefaultValueFromFlag;\r
a7f87053 1864 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
1865 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1866 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1867 InsertDefaultValue (BlockData, &DefaultData);\r
1868 } \r
1869 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
1870 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1871 InsertDefaultValue (BlockData, &DefaultData);\r
84f9a9ec 1872 }\r
84f9a9ec 1873\r
ef40f0f6
ED
1874 \r
1875 }\r
1876 \r
1877 //\r
1878 // 2. Set as the default value when this is the first option.\r
1879 // The first oneof option value will be used as default value when no default value is specified. \r
1880 //\r
1881 if (FirstOneOfOption) {\r
1882 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
1883 FirstOneOfOption = FALSE;\r
1884 \r
84f9a9ec
LG
1885 //\r
1886 // Prepare new DefaultValue\r
ef40f0f6 1887 // \r
eb5e7d3e 1888 DefaultData.Type = DefaultValueFromDefault;\r
a7f87053 1889 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
1890 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
1891 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
1892 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1893 InsertDefaultValue (BlockData, &DefaultData);\r
1894 } \r
84f9a9ec
LG
1895 }\r
1896 break;\r
1897\r
1898 case EFI_IFR_DEFAULT_OP:\r
1899 //\r
1900 // Update Current BlockData to the default value.\r
1901 //\r
1902 if (BlockData == NULL || BlockData->Scope == 0) {\r
1903 //\r
1904 // No matched block data is ignored. \r
1905 //\r
1906 break;\r
1907 }\r
1908\r
1909 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1910 //\r
1911 // OrderedList Opcode is no default value.\r
1912 //\r
1913 break;\r
1914 }\r
1915 //\r
81b618fe 1916 // Get the DefaultId\r
84f9a9ec
LG
1917 //\r
1918 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
1919 VarDefaultId = IfrDefault->DefaultId;\r
84f9a9ec
LG
1920 //\r
1921 // Prepare new DefaultValue\r
1922 //\r
eb5e7d3e 1923 DefaultData.Type = DefaultValueFromOpcode;\r
ef40f0f6 1924 DefaultData.DefaultId = VarDefaultId;\r
23fe74dc 1925 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
ef40f0f6
ED
1926 \r
1927 // If the value field is expression, set the cleaned flag.\r
1928 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
1929 DefaultData.Cleaned = TRUE;\r
84f9a9ec 1930 }\r
84f9a9ec
LG
1931 //\r
1932 // Add DefaultValue into current BlockData\r
1933 //\r
ef40f0f6
ED
1934 InsertDefaultValue (BlockData, &DefaultData);\r
1935 \r
1936 //\r
1937 // After insert the default value, reset the cleaned value for next \r
1938 // time used. If not set here, need to set the value before everytime \r
1939 // use it.\r
1940 //\r
1941 DefaultData.Cleaned = FALSE;\r
84f9a9ec
LG
1942 break;\r
1943 case EFI_IFR_END_OP:\r
1944 //\r
8567300a 1945 // End Opcode is for Var question.\r
84f9a9ec
LG
1946 //\r
1947 if (BlockData != NULL && BlockData->Scope > 0) {\r
1948 BlockData->Scope--;\r
1949 }\r
1950 break;\r
1951 default:\r
1952 if (BlockData != NULL && BlockData->Scope > 0) {\r
1953 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
1954 }\r
1955 break;\r
1956 }\r
1957\r
1958 IfrOffset += IfrOpHdr->Length;\r
1959 }\r
1960\r
1961Done:\r
ef40f0f6
ED
1962 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
1963 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
1964 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
1965 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
1966 LinkDefault = LinkDefault->ForwardLink;\r
1967 if (DefaultDataPtr->Cleaned == TRUE) {\r
1968 RemoveEntryList (&DefaultDataPtr->Entry);\r
1969 FreePool (DefaultDataPtr);\r
1970 }\r
1971 }\r
1972 }\r
1973\r
84f9a9ec
LG
1974 return Status; \r
1975}\r
1976\r
1977/**\r
1978 This function gets the full request string and full default value string by \r
1979 parsing IFR data in HII form packages. \r
1980 \r
1981 When Request points to NULL string, the request string and default value string \r
1982 for each varstore in form package will return. \r
1983\r
8567300a 1984 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
84f9a9ec
LG
1985 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
1986 @param Request Pointer to a null-terminated Unicode string in\r
1987 <ConfigRequest> format. When it doesn't contain\r
1988 any RequestElement, it will be updated to return \r
1989 the full RequestElement retrieved from IFR data.\r
1990 If it points to NULL, the request string for the first\r
1991 varstore in form package will be merged into a\r
1992 <MultiConfigRequest> format string and return. \r
1993 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
1994 <ConfigAltResp> format. When the pointer is to NULL,\r
1995 the full default value string retrieved from IFR data\r
1996 will return. When the pinter is to a string, the\r
1997 full default value string retrieved from IFR data\r
1998 will be merged into the input string and return.\r
1999 When Request points to NULL, the default value string \r
2000 for each varstore in form package will be merged into \r
2001 a <MultiConfigAltResp> format string and return.\r
ae79d2f9
LG
2002 @param PointerProgress Optional parameter, it can be be NULL. \r
2003 When it is not NULL, if Request is NULL, it returns NULL. \r
2004 On return, points to a character in the Request\r
2005 string. Points to the string's null terminator if\r
2006 request was successful. Points to the most recent\r
2007 & before the first failing name / value pair (or\r
2008 the beginning of the string if the failure is in\r
2009 the first name / value pair) if the request was\r
2010 not successful.\r
84f9a9ec
LG
2011 @retval EFI_SUCCESS The Results string is set to the full request string.\r
2012 And AltCfgResp contains all default value string.\r
2013 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
2014 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
2015 can't be found in Form package.\r
2016 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 2017 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
2018\r
2019**/\r
2020EFI_STATUS\r
2021EFIAPI\r
2022GetFullStringFromHiiFormPackages (\r
8567300a 2023 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
2024 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2025 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
2026 IN OUT EFI_STRING *AltCfgResp,\r
2027 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
2028 )\r
2029{\r
2030 EFI_STATUS Status;\r
8567300a
LG
2031 UINT8 *HiiFormPackage;\r
2032 UINTN PackageSize;\r
84f9a9ec
LG
2033 IFR_BLOCK_DATA *RequestBlockArray;\r
2034 IFR_BLOCK_DATA *BlockData;\r
2035 IFR_BLOCK_DATA *NextBlockData;\r
2036 IFR_DEFAULT_DATA *DefaultValueData;\r
2037 IFR_DEFAULT_DATA *DefaultId;\r
2038 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
2039 IFR_VARSTORAGE_DATA *VarStorageData;\r
2040 EFI_STRING DefaultAltCfgResp;\r
2041 EFI_STRING FullConfigRequest;\r
2042 EFI_STRING ConfigHdr;\r
2043 EFI_STRING GuidStr;\r
2044 EFI_STRING NameStr;\r
2045 EFI_STRING PathStr;\r
2046 EFI_STRING StringPtr;\r
ae79d2f9 2047 EFI_STRING Progress;\r
84f9a9ec
LG
2048 UINTN Length;\r
2049 UINT8 *TmpBuffer;\r
2050 UINT16 Offset;\r
2051 UINT16 Width;\r
2052 LIST_ENTRY *Link;\r
2053 LIST_ENTRY *LinkData;\r
2054 LIST_ENTRY *LinkDefault;\r
6e3f5b2a 2055 BOOLEAN DataExist;\r
84f9a9ec 2056\r
ae79d2f9
LG
2057 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
2058 return EFI_INVALID_PARAMETER;\r
2059 }\r
2060\r
84f9a9ec
LG
2061 //\r
2062 // Initialize the local variables.\r
2063 //\r
2064 RequestBlockArray = NULL;\r
8567300a 2065 DefaultIdArray = NULL;\r
84f9a9ec
LG
2066 VarStorageData = NULL;\r
2067 DefaultAltCfgResp = NULL;\r
2068 FullConfigRequest = NULL;\r
2069 ConfigHdr = NULL;\r
84f9a9ec
LG
2070 GuidStr = NULL;\r
2071 NameStr = NULL;\r
2072 PathStr = NULL;\r
8567300a 2073 HiiFormPackage = NULL;\r
8567300a 2074 PackageSize = 0;\r
6e3f5b2a 2075 DataExist = FALSE;\r
ae79d2f9 2076 Progress = *Request;\r
84f9a9ec 2077\r
cce6230f 2078 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
84f9a9ec 2079 if (EFI_ERROR (Status)) {\r
cce6230f 2080 return Status;\r
84f9a9ec
LG
2081 }\r
2082\r
2083 //\r
8567300a 2084 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
2085 //\r
2086 StringPtr = NULL;\r
2087 if (*Request != NULL) {\r
ae79d2f9
LG
2088 StringPtr = *Request;\r
2089 //\r
2090 // Jump <ConfigHdr>\r
2091 //\r
2092 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2093 Status = EFI_INVALID_PARAMETER;\r
2094 goto Done;\r
2095 }\r
2096 StringPtr += StrLen (L"GUID=");\r
2097 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
2098 StringPtr++;\r
2099 }\r
2100 if (*StringPtr == L'\0') {\r
2101 Status = EFI_INVALID_PARAMETER;\r
2102 goto Done;\r
2103 }\r
2104 StringPtr += StrLen (L"&NAME=");\r
2105 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
2106 StringPtr++;\r
2107 }\r
2108 if (*StringPtr == L'\0') {\r
2109 Status = EFI_INVALID_PARAMETER;\r
2110 goto Done;\r
2111 }\r
2112 StringPtr += StrLen (L"&PATH=");\r
2113 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2114 StringPtr ++;\r
2115 }\r
2116 //\r
2117 // Check the following string &OFFSET=\r
2118 //\r
2119 if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
2120 Progress = StringPtr;\r
2121 Status = EFI_INVALID_PARAMETER;\r
2122 goto Done;\r
2123 } else if (*StringPtr == L'\0') {\r
2124 //\r
2125 // No request block is found.\r
2126 //\r
2127 StringPtr = NULL;\r
2128 }\r
84f9a9ec
LG
2129 }\r
2130 if (StringPtr != NULL) {\r
2131 //\r
2132 // Init RequestBlockArray\r
2133 //\r
2134 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2135 if (RequestBlockArray == NULL) {\r
2136 Status = EFI_OUT_OF_RESOURCES;\r
2137 goto Done;\r
2138 }\r
2139 InitializeListHead (&RequestBlockArray->Entry);\r
2140\r
2141 //\r
2142 // Get the request Block array from the request string\r
2143 // Offset and Width\r
2144 //\r
2145\r
2146 //\r
2147 // Parse each <RequestElement> if exists\r
2148 // Only <BlockName> format is supported by this help function.\r
2149 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
2150 //\r
2151 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
2152 //\r
2153 // Skip the OFFSET string\r
ae79d2f9
LG
2154 //\r
2155 Progress = StringPtr;\r
84f9a9ec
LG
2156 StringPtr += StrLen (L"&OFFSET=");\r
2157 //\r
2158 // Get Offset\r
2159 //\r
2160 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2161 if (EFI_ERROR (Status)) {\r
2162 goto Done;\r
2163 }\r
2164 Offset = 0;\r
2165 CopyMem (\r
2166 &Offset,\r
2167 TmpBuffer,\r
2168 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2169 );\r
2170 FreePool (TmpBuffer);\r
2171 \r
2172 StringPtr += Length;\r
2173 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2174 Status = EFI_INVALID_PARAMETER;\r
2175 goto Done;\r
2176 }\r
2177 StringPtr += StrLen (L"&WIDTH=");\r
2178 \r
2179 //\r
2180 // Get Width\r
2181 //\r
2182 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2183 if (EFI_ERROR (Status)) {\r
2184 goto Done;\r
2185 }\r
2186 Width = 0;\r
2187 CopyMem (\r
2188 &Width,\r
2189 TmpBuffer,\r
2190 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2191 );\r
2192 FreePool (TmpBuffer);\r
2193\r
2194 StringPtr += Length;\r
2195 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2196 Status = EFI_INVALID_PARAMETER;\r
2197 goto Done;\r
2198 }\r
2199 \r
2200 //\r
2201 // Set Block Data\r
2202 //\r
2203 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2204 if (BlockData == NULL) {\r
2205 Status = EFI_OUT_OF_RESOURCES;\r
2206 goto Done;\r
2207 }\r
2208 BlockData->Offset = Offset;\r
2209 BlockData->Width = Width;\r
2210 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
6e3f5b2a
LG
2211 \r
2212 //\r
2213 // Skip &VALUE string if &VALUE does exists.\r
2214 //\r
2215 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
2216 StringPtr += StrLen (L"&VALUE=");\r
84f9a9ec 2217\r
6e3f5b2a
LG
2218 //\r
2219 // Get Value\r
2220 //\r
2221 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2222 if (EFI_ERROR (Status)) {\r
2223 Status = EFI_INVALID_PARAMETER;\r
2224 goto Done;\r
2225 }\r
2226\r
2227 StringPtr += Length;\r
2228 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2229 Status = EFI_INVALID_PARAMETER;\r
2230 goto Done;\r
2231 }\r
2232 }\r
84f9a9ec
LG
2233 //\r
2234 // If '\0', parsing is finished. \r
2235 //\r
2236 if (*StringPtr == 0) {\r
2237 break;\r
2238 }\r
2239 }\r
2240 \r
2241 //\r
2242 // Merge the requested block data.\r
2243 //\r
2244 Link = RequestBlockArray->Entry.ForwardLink;\r
2245 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
2246 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2247 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
2248 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
2249 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
2250 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
2251 }\r
2252 RemoveEntryList (Link->ForwardLink);\r
2253 FreePool (NextBlockData);\r
2254 continue;\r
2255 }\r
2256 Link = Link->ForwardLink; \r
2257 }\r
2258 }\r
2259 \r
2260 //\r
8567300a 2261 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 2262 //\r
84f9a9ec 2263\r
8567300a
LG
2264 //\r
2265 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
2266 //\r
2267 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
2268 if (DefaultIdArray == NULL) {\r
2269 Status = EFI_OUT_OF_RESOURCES;\r
2270 goto Done;\r
2271 }\r
2272 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 2273\r
8567300a
LG
2274 //\r
2275 // Initialize VarStorageData to store the var store Block and Default value information.\r
2276 //\r
2277 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
2278 if (VarStorageData == NULL) {\r
2279 Status = EFI_OUT_OF_RESOURCES;\r
2280 goto Done;\r
2281 }\r
2282 InitializeListHead (&VarStorageData->Entry);\r
2283 InitializeListHead (&VarStorageData->BlockEntry);\r
84f9a9ec 2284\r
8567300a
LG
2285 //\r
2286 // Parse the opcode in form pacakge to get the default setting.\r
2287 //\r
2288 Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);\r
2289 if (EFI_ERROR (Status)) {\r
2290 goto Done;\r
84f9a9ec 2291 }\r
76c24251
LG
2292 \r
2293 //\r
2294 // No requested varstore in IFR data and directly return\r
2295 //\r
2296 if (VarStorageData->Size == 0) {\r
6e3f5b2a 2297 Status = EFI_SUCCESS;\r
76c24251
LG
2298 goto Done;\r
2299 }\r
84f9a9ec
LG
2300\r
2301 //\r
2302 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
2303 //\r
2304\r
2305 //\r
2306 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
2307 //\r
2308 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
2309 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
2310 GenerateSubStr (\r
2311 L"PATH=",\r
2312 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2313 (VOID *) DevicePath,\r
2314 1,\r
2315 &PathStr\r
2316 );\r
2317 Length = StrLen (GuidStr);\r
2318 Length = Length + StrLen (NameStr);\r
2319 Length = Length + StrLen (PathStr) + 1;\r
2320 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
2321 if (ConfigHdr == NULL) {\r
2322 Status = EFI_OUT_OF_RESOURCES;\r
2323 goto Done; \r
2324 }\r
2325 StrCpy (ConfigHdr, GuidStr);\r
2326 StrCat (ConfigHdr, NameStr);\r
2327 StrCat (ConfigHdr, PathStr);\r
2328\r
2329 //\r
2330 // Remove the last character L'&'\r
2331 //\r
2332 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
2333\r
2334 if (RequestBlockArray == NULL) {\r
2335 //\r
2336 // Append VarStorageData BlockEntry into *Request string\r
2337 // Now support only one varstore in a form package.\r
2338 //\r
2339\r
2340 //\r
2341 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
2342 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
2343 //\r
2344\r
2345 //\r
2346 // Compute the length of the entire request starting with <ConfigHdr> and a \r
2347 // Null-terminator\r
2348 //\r
ae79d2f9
LG
2349 DataExist = FALSE;\r
2350 Length = StrLen (ConfigHdr) + 1;\r
84f9a9ec
LG
2351\r
2352 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2353 //\r
2354 // Add <BlockName> length for each Offset/Width pair\r
2355 //\r
2356 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
2357 // | 8 | 4 | 7 | 4 |\r
2358 //\r
6e3f5b2a 2359 DataExist = TRUE;\r
84f9a9ec
LG
2360 Length = Length + (8 + 4 + 7 + 4);\r
2361 }\r
2362 \r
6e3f5b2a
LG
2363 //\r
2364 // No any request block data is found. The request string can't be constructed.\r
2365 //\r
2366 if (!DataExist) {\r
2367 Status = EFI_SUCCESS;\r
2368 goto Done;\r
2369 }\r
2370\r
84f9a9ec
LG
2371 //\r
2372 // Allocate buffer for the entire <ConfigRequest>\r
2373 //\r
2374 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
2375 if (FullConfigRequest == NULL) {\r
6e3f5b2a 2376 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2377 goto Done;\r
2378 }\r
2379 StringPtr = FullConfigRequest;\r
2380 \r
2381 //\r
2382 // Start with <ConfigHdr>\r
2383 //\r
2384 StrCpy (StringPtr, ConfigHdr);\r
2385 StringPtr += StrLen (StringPtr);\r
2386\r
2387 //\r
2388 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
2389 //\r
2390 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2391 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2392 //\r
2393 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
2394 //\r
2395 UnicodeSPrint (\r
2396 StringPtr, \r
2397 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
2398 L"&OFFSET=%04X&WIDTH=%04X", \r
2399 BlockData->Offset, \r
2400 BlockData->Width\r
2401 );\r
2402 StringPtr += StrLen (StringPtr);\r
2403 }\r
2404 //\r
2405 // Set to the got full request string.\r
2406 //\r
2407 HiiToLower (FullConfigRequest);\r
2408 if (*Request != NULL) {\r
2409 FreePool (*Request);\r
2410 }\r
2411 *Request = FullConfigRequest;\r
2412 }\r
2413 \r
2414 //\r
2415 // 4. Construct Default Value string in AltResp according to request element.\r
2416 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
2417 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
2418 //\r
6e3f5b2a 2419 DataExist = FALSE;\r
93e3992d 2420 //\r
84f9a9ec 2421 // Add length for <ConfigHdr> + '\0'\r
93e3992d 2422 //\r
84f9a9ec
LG
2423 Length = StrLen (ConfigHdr) + 1;\r
2424 \r
2425 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2426 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2427 //\r
2428 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2429 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2430 //\r
2431 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2432 \r
2433 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2434 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2435 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2436 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2437 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2438 //\r
2439 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2440 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2441 //\r
6e3f5b2a
LG
2442 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2443 DataExist = TRUE;\r
84f9a9ec
LG
2444 }\r
2445 }\r
2446 }\r
93e3992d 2447 }\r
6e3f5b2a
LG
2448 \r
2449 //\r
2450 // No default value is found. The default string doesn't exist.\r
2451 //\r
2452 if (!DataExist) {\r
2453 Status = EFI_SUCCESS;\r
2454 goto Done;\r
2455 }\r
84f9a9ec 2456\r
93e3992d 2457 //\r
84f9a9ec 2458 // Allocate buffer for the entire <DefaultAltCfgResp>\r
93e3992d 2459 //\r
84f9a9ec
LG
2460 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2461 if (DefaultAltCfgResp == NULL) {\r
6e3f5b2a 2462 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2463 goto Done;\r
2464 }\r
2465 StringPtr = DefaultAltCfgResp;\r
93e3992d 2466\r
84f9a9ec
LG
2467 //\r
2468 // Start with <ConfigHdr>\r
2469 //\r
2470 StrCpy (StringPtr, ConfigHdr);\r
2471 StringPtr += StrLen (StringPtr);\r
93e3992d 2472\r
84f9a9ec
LG
2473 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2474 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2475 //\r
2476 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2477 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2478 //\r
2479 UnicodeSPrint (\r
2480 StringPtr, \r
2481 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2482 L"&%s&ALTCFG=%04X", \r
2483 ConfigHdr, \r
81b618fe 2484 DefaultId->DefaultId\r
84f9a9ec
LG
2485 );\r
2486 StringPtr += StrLen (StringPtr);\r
2487 \r
2488 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2489 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2490 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2491 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2492 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2493 //\r
2494 // Add <BlockConfig>\r
2495 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2496 //\r
2497 UnicodeSPrint (\r
2498 StringPtr, \r
2499 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2500 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2501 BlockData->Offset, \r
2502 BlockData->Width\r
2503 );\r
2504 StringPtr += StrLen (StringPtr);\r
2505\r
2506 //\r
2507 // Convert Value to a hex string in "%x" format\r
2508 // NOTE: This is in the opposite byte that GUID and PATH use\r
2509 //\r
2510 Width = BlockData->Width;\r
2511 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2512 for (; Width > 0; Width--) {\r
2513 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2514 }\r
2515 }\r
2516 }\r
2517 }\r
93e3992d 2518 }\r
84f9a9ec 2519 HiiToLower (DefaultAltCfgResp);\r
93e3992d 2520\r
84f9a9ec
LG
2521 //\r
2522 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
2523 //\r
6e3f5b2a 2524 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
2525 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
2526 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
2527 } else if (*AltCfgResp == NULL) {\r
2528 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 2529 }\r
93e3992d 2530\r
84f9a9ec
LG
2531Done:\r
2532 if (RequestBlockArray != NULL) {\r
2533 //\r
2534 // Free Link Array RequestBlockArray\r
2535 //\r
2536 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2537 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2538 RemoveEntryList (&BlockData->Entry);\r
2539 FreePool (BlockData);\r
2540 }\r
2541\r
2542 FreePool (RequestBlockArray);\r
93e3992d 2543 }\r
63d55bb9 2544 \r
84f9a9ec
LG
2545 if (VarStorageData != NULL) {\r
2546 //\r
2547 // Free link array VarStorageData\r
2548 //\r
2549 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
2550 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2551 RemoveEntryList (&BlockData->Entry);\r
2552 //\r
2553 // Free default value link array\r
2554 //\r
2555 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
2556 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2557 RemoveEntryList (&DefaultValueData->Entry);\r
2558 FreePool (DefaultValueData);\r
2559 }\r
2560 FreePool (BlockData);\r
63d55bb9 2561 }\r
84f9a9ec 2562 FreePool (VarStorageData);\r
93e3992d 2563 }\r
2564\r
84f9a9ec
LG
2565 if (DefaultIdArray != NULL) {\r
2566 //\r
2567 // Free DefaultId Array\r
2568 //\r
2569 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
2570 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2571 RemoveEntryList (&DefaultId->Entry);\r
2572 FreePool (DefaultId);\r
2573 }\r
2574 FreePool (DefaultIdArray);\r
2575 }\r
2576 \r
2577 //\r
2578 // Free the allocated string \r
2579 //\r
2580 if (GuidStr != NULL) {\r
2581 FreePool (GuidStr);\r
2582 }\r
2583 if (NameStr != NULL) {\r
2584 FreePool (NameStr);\r
2585 }\r
2586 if (PathStr != NULL) {\r
2587 FreePool (PathStr);\r
2588 }\r
2589 if (ConfigHdr != NULL) {\r
2590 FreePool (ConfigHdr);\r
2591 }\r
93e3992d 2592\r
84f9a9ec
LG
2593 //\r
2594 // Free Pacakge data\r
2595 //\r
8567300a
LG
2596 if (HiiFormPackage != NULL) {\r
2597 FreePool (HiiFormPackage);\r
676df92c 2598 }\r
63d55bb9 2599\r
ae79d2f9
LG
2600 if (PointerProgress != NULL) {\r
2601 if (*Request == NULL) {\r
2602 *PointerProgress = NULL;\r
2603 } else if (EFI_ERROR (Status)) {\r
2604 *PointerProgress = Progress;\r
2605 } else {\r
2606 *PointerProgress = *Request + StrLen (*Request);\r
2607 }\r
2608 }\r
2609\r
93e3992d 2610 return Status;\r
2611}\r
2612\r
cce6230f
ED
2613/**\r
2614 This function gets the full request resp string by \r
2615 parsing IFR data in HII form packages.\r
2616\r
2617 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2618 instance.\r
2619 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
2620 varstore data structure. \r
2621 @param Request Pointer to a null-terminated Unicode string in\r
2622 <ConfigRequest> format.\r
2623 @param RequestResp Pointer to a null-terminated Unicode string in\r
2624 <ConfigResp> format.\r
2625 @param AccessProgress On return, points to a character in the Request\r
2626 string. Points to the string's null terminator if\r
2627 request was successful. Points to the most recent\r
2628 & before the first failing name / value pair (or\r
2629 the beginning of the string if the failure is in\r
2630 the first name / value pair) if the request was\r
2631 not successful.\r
2632\r
2633 @retval EFI_SUCCESS The Results string is set to the full request string.\r
2634 And AltCfgResp contains all default value string.\r
2635 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
2636 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
2637\r
2638**/\r
2639EFI_STATUS\r
2640GetConfigRespFromEfiVarStore (\r
2641 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2642 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
2643 IN EFI_STRING Request,\r
2644 OUT EFI_STRING *RequestResp,\r
2645 OUT EFI_STRING *AccessProgress\r
2646 )\r
2647{\r
2648 EFI_STATUS Status;\r
2649 EFI_STRING VarStoreName;\r
2650 UINT8 *VarStore;\r
2651 UINTN BufferSize;\r
2652\r
2653 Status = EFI_SUCCESS;\r
2654 BufferSize = 0;\r
2655 VarStore = NULL;\r
2656 VarStoreName = NULL;\r
2657 \r
2658 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
2659 if (VarStoreName == NULL) {\r
2660 Status = EFI_OUT_OF_RESOURCES;\r
2661 goto Done;\r
2662 }\r
2663 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
2664 \r
2665 \r
2666 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
2667 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2668 goto Done;\r
2669 }\r
2670\r
2671 VarStore = AllocateZeroPool (BufferSize);\r
2672 ASSERT (VarStore != NULL);\r
2673 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
2674 if (EFI_ERROR (Status)) {\r
2675 goto Done;\r
2676 }\r
2677\r
2678 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
2679 if (EFI_ERROR (Status)) {\r
2680 goto Done;\r
2681 }\r
2682\r
2683Done:\r
2684 if (VarStoreName != NULL) {\r
2685 FreePool (VarStoreName);\r
2686 }\r
2687\r
2688 if (VarStore != NULL) {\r
2689 FreePool (VarStore);\r
2690 }\r
2691\r
2692 return Status;\r
2693}\r
2694\r
2695\r
2696/**\r
2697 This function route the full request resp string for efi varstore. \r
2698\r
2699 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2700 instance.\r
2701 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
2702 varstore data structure. \r
2703 @param RequestResp Pointer to a null-terminated Unicode string in\r
2704 <ConfigResp> format.\r
2705 @param Result Pointer to a null-terminated Unicode string in\r
2706 <ConfigResp> format.\r
2707 \r
2708 @retval EFI_SUCCESS The Results string is set to the full request string.\r
2709 And AltCfgResp contains all default value string.\r
2710 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
2711 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
2712\r
2713**/\r
2714EFI_STATUS\r
2715RouteConfigRespForEfiVarStore (\r
2716 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2717 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
2718 IN EFI_STRING RequestResp,\r
2719 OUT EFI_STRING *Result\r
2720 )\r
2721{\r
2722 EFI_STATUS Status;\r
2723 EFI_STRING VarStoreName;\r
f26b6a9c 2724 UINT8 *VarStore;\r
cce6230f
ED
2725 UINTN BufferSize;\r
2726 UINTN BlockSize;\r
2727\r
2728 Status = EFI_SUCCESS;\r
2729 BufferSize = 0;\r
2730 VarStore = NULL;\r
2731 VarStoreName = NULL;\r
2732\r
2733 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
2734 if (VarStoreName == NULL) {\r
2735 Status = EFI_OUT_OF_RESOURCES;\r
2736 goto Done;\r
2737 }\r
2738 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
2739 \r
2740 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
2741 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2742 goto Done;\r
2743 }\r
2744\r
2745 BlockSize = BufferSize;\r
2746 VarStore = AllocateZeroPool (BufferSize);\r
2747 ASSERT (VarStore != NULL);\r
2748 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
2749 if (EFI_ERROR (Status)) {\r
2750 goto Done;\r
2751 }\r
2752\r
2753 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
2754 if (EFI_ERROR (Status)) {\r
2755 goto Done;\r
2756 }\r
2757\r
2758 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
2759 if (EFI_ERROR (Status)) {\r
2760 goto Done;\r
2761 }\r
2762\r
2763Done:\r
2764 if (VarStoreName != NULL) {\r
2765 FreePool (VarStoreName);\r
2766 }\r
2767\r
2768 if (VarStore != NULL) {\r
2769 FreePool (VarStore);\r
2770 }\r
2771\r
2772 return Status;\r
2773}\r
2774\r
93e3992d 2775/**\r
2776 This function allows a caller to extract the current configuration\r
2777 for one or more named elements from one or more drivers.\r
2778\r
2779 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2780 instance.\r
2781 @param Request A null-terminated Unicode string in\r
2782 <MultiConfigRequest> format.\r
2783 @param Progress On return, points to a character in the Request\r
2784 string. Points to the string's null terminator if\r
2785 request was successful. Points to the most recent\r
2786 & before the first failing name / value pair (or\r
2787 the beginning of the string if the failure is in\r
2788 the first name / value pair) if the request was\r
2789 not successful.\r
2790 @param Results Null-terminated Unicode string in\r
2791 <MultiConfigAltResp> format which has all values\r
2792 filled in for the names in the Request string.\r
2793 String to be allocated by the called function.\r
2794\r
2795 @retval EFI_SUCCESS The Results string is filled with the values\r
2796 corresponding to all requested names.\r
2797 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2798 results that must be stored awaiting possible\r
2799 future protocols.\r
2800 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
2801 Progress set to the "G" in "GUID" of the routing\r
2802 header that doesn't match. Note: There is no\r
2803 requirement that all routing data be validated\r
2804 before any configuration extraction.\r
2805 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
2806 parameter would result in this type of error. The\r
2807 Progress parameter is set to NULL.\r
2808 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
2809 before the error or the beginning of the string.\r
2810 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
2811 name in question.\r
2812\r
2813**/\r
2814EFI_STATUS\r
2815EFIAPI\r
2816HiiConfigRoutingExtractConfig (\r
2817 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2818 IN CONST EFI_STRING Request,\r
2819 OUT EFI_STRING *Progress,\r
2820 OUT EFI_STRING *Results\r
2821 )\r
2822{\r
84f9a9ec 2823 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2824 EFI_STRING StringPtr;\r
2825 EFI_STRING ConfigRequest;\r
2826 UINTN Length;\r
2827 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2828 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 2829 EFI_STATUS Status;\r
84f9a9ec
LG
2830 LIST_ENTRY *Link;\r
2831 HII_DATABASE_RECORD *Database;\r
2832 UINT8 *DevicePathPkg;\r
2833 UINT8 *CurrentDevicePath;\r
93e3992d 2834 EFI_HANDLE DriverHandle;\r
84f9a9ec 2835 EFI_HII_HANDLE HiiHandle;\r
93e3992d 2836 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2837 EFI_STRING AccessProgress;\r
2838 EFI_STRING AccessResults;\r
84f9a9ec 2839 EFI_STRING DefaultResults;\r
8d00a0f1 2840 BOOLEAN FirstElement;\r
6e3f5b2a 2841 BOOLEAN IfrDataParsedFlag;\r
cce6230f
ED
2842 BOOLEAN IsEfiVarStore;\r
2843 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo; \r
93e3992d 2844\r
2845 if (This == NULL || Progress == NULL || Results == NULL) {\r
2846 return EFI_INVALID_PARAMETER;\r
2847 }\r
2848\r
2849 if (Request == NULL) {\r
2850 *Progress = NULL;\r
2851 return EFI_INVALID_PARAMETER;\r
2852 }\r
2853\r
84f9a9ec 2854 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2855 StringPtr = Request;\r
2856 *Progress = StringPtr;\r
84f9a9ec
LG
2857 DefaultResults = NULL;\r
2858 ConfigRequest = NULL;\r
2859 Status = EFI_SUCCESS;\r
2860 AccessResults = NULL;\r
cce6230f 2861 AccessProgress = NULL;\r
84f9a9ec 2862 DevicePath = NULL;\r
6e3f5b2a 2863 IfrDataParsedFlag = FALSE;\r
cce6230f
ED
2864 IsEfiVarStore = FALSE;\r
2865 EfiVarStoreInfo = NULL;\r
93e3992d 2866\r
2867 //\r
2868 // The first element of <MultiConfigRequest> should be\r
2869 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2870 //\r
2871 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2872 return EFI_INVALID_PARAMETER;\r
2873 }\r
2874\r
8d00a0f1 2875 FirstElement = TRUE;\r
2876\r
93e3992d 2877 //\r
2878 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2879 // Results if this fix length is insufficient.\r
2880 //\r
2881 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2882 if (*Results == NULL) {\r
2883 return EFI_OUT_OF_RESOURCES;\r
2884 }\r
2885\r
2886 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2887 //\r
2888 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
2889 // or most recent & before the error.\r
2890 //\r
2891 if (StringPtr == Request) {\r
2892 *Progress = StringPtr;\r
2893 } else {\r
2894 *Progress = StringPtr - 1;\r
2895 }\r
2896\r
2897 //\r
2898 // Process each <ConfigRequest> of <MultiConfigRequest>\r
2899 //\r
2900 Length = CalculateConfigStringLen (StringPtr);\r
2901 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2902 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
2903 Status = EFI_OUT_OF_RESOURCES;\r
2904 goto Done;\r
93e3992d 2905 }\r
2906 *(ConfigRequest + Length) = 0;\r
2907\r
2908 //\r
2909 // Get the UEFI device path\r
2910 //\r
2911 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
2912 if (EFI_ERROR (Status)) {\r
84f9a9ec 2913 goto Done;\r
93e3992d 2914 }\r
2915\r
2916 //\r
84f9a9ec
LG
2917 // Find driver which matches the routing data.\r
2918 //\r
2919 DriverHandle = NULL;\r
2920 HiiHandle = NULL;\r
8567300a 2921 Database = NULL;\r
84f9a9ec
LG
2922 for (Link = Private->DatabaseList.ForwardLink;\r
2923 Link != &Private->DatabaseList;\r
2924 Link = Link->ForwardLink\r
2925 ) {\r
2926 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
2927 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2928 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2929 if (CompareMem (\r
84f9a9ec
LG
2930 DevicePath,\r
2931 CurrentDevicePath,\r
6e3f5b2a
LG
2932 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2933 ) == 0) {\r
84f9a9ec
LG
2934 DriverHandle = Database->DriverHandle;\r
2935 HiiHandle = Database->Handle;\r
2936 break;\r
2937 }\r
2938 }\r
2939 }\r
2940 \r
2941 //\r
2942 // Try to find driver handle by device path.\r
93e3992d 2943 //\r
84f9a9ec
LG
2944 if (DriverHandle == NULL) {\r
2945 TempDevicePath = DevicePath;\r
2946 Status = gBS->LocateDevicePath (\r
2947 &gEfiDevicePathProtocolGuid,\r
2948 &TempDevicePath,\r
2949 &DriverHandle\r
2950 );\r
2951 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2952 //\r
2953 // Routing data does not match any known driver.\r
2954 // Set Progress to the 'G' in "GUID" of the routing header.\r
2955 //\r
2956 *Progress = StringPtr;\r
2957 Status = EFI_NOT_FOUND;\r
2958 goto Done;\r
2959 }\r
2960 }\r
2961 \r
2962 //\r
2963 // Check whether ConfigRequest contains request string OFFSET/WIDTH\r
2964 //\r
6e3f5b2a 2965 IfrDataParsedFlag = FALSE;\r
84f9a9ec 2966 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {\r
93e3992d 2967 //\r
84f9a9ec 2968 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 2969 //\r
6e3f5b2a 2970 IfrDataParsedFlag = TRUE;\r
ae79d2f9 2971 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 2972 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
2973 //\r
2974 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2975 // Map it to the progress on <MultiConfigRequest> then return it.\r
2976 //\r
2977 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
2978 goto Done;\r
2979 }\r
1f1cb2f2
LG
2980 //\r
2981 // Not any request block is found.\r
2982 //\r
2983 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {\r
76c24251 2984 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
2985 goto NextConfigString;\r
2986 }\r
93e3992d 2987 }\r
2988\r
2989 //\r
cce6230f 2990 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 2991 //\r
cce6230f
ED
2992 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
2993 if (EFI_ERROR (Status)) {\r
2994 goto Done;\r
2995 }\r
2996 \r
2997 if (IsEfiVarStore) {\r
2998 //\r
2999 // Call the GetVariable function to extract settings.\r
3000 //\r
3001 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
3002 FreePool (EfiVarStoreInfo); \r
3003 } else {\r
3004 //\r
3005 // Call corresponding ConfigAccess protocol to extract settings\r
3006 //\r
3007 Status = gBS->HandleProtocol (\r
3008 DriverHandle,\r
3009 &gEfiHiiConfigAccessProtocolGuid,\r
3010 (VOID **) &ConfigAccess\r
3011 );\r
3012 ASSERT_EFI_ERROR (Status);\r
93e3992d 3013\r
cce6230f
ED
3014 Status = ConfigAccess->ExtractConfig (\r
3015 ConfigAccess,\r
3016 ConfigRequest,\r
3017 &AccessProgress,\r
3018 &AccessResults\r
3019 );\r
3020 }\r
93e3992d 3021 if (EFI_ERROR (Status)) {\r
3022 //\r
3023 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3024 // Map it to the progress on <MultiConfigRequest> then return it.\r
3025 //\r
8d00a0f1 3026 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 3027 goto Done;\r
93e3992d 3028 }\r
3029\r
3030 //\r
8d00a0f1 3031 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3032 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 3033 //\r
3034 ASSERT (*AccessProgress == 0);\r
8d00a0f1 3035\r
84f9a9ec
LG
3036 //\r
3037 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3038 //\r
ae79d2f9
LG
3039 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
3040 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3041 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3042 }\r
ae79d2f9 3043\r
84f9a9ec
LG
3044 FreePool (DevicePath);\r
3045 DevicePath = NULL;\r
84f9a9ec 3046\r
ae79d2f9
LG
3047 if (DefaultResults != NULL) {\r
3048 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3049 ASSERT_EFI_ERROR (Status);\r
3050 FreePool (DefaultResults);\r
3051 DefaultResults = NULL;\r
3052 }\r
3053 \r
76c24251 3054NextConfigString: \r
8d00a0f1 3055 if (!FirstElement) {\r
3056 Status = AppendToMultiString (Results, L"&");\r
3057 ASSERT_EFI_ERROR (Status);\r
3058 }\r
3059 \r
93e3992d 3060 Status = AppendToMultiString (Results, AccessResults);\r
3061 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 3062\r
3063 FirstElement = FALSE;\r
84f9a9ec 3064\r
676df92c 3065 FreePool (AccessResults);\r
93e3992d 3066 AccessResults = NULL;\r
676df92c 3067 FreePool (ConfigRequest);\r
93e3992d 3068 ConfigRequest = NULL;\r
3069\r
3070 //\r
3071 // Go to next <ConfigRequest> (skip '&').\r
3072 //\r
3073 StringPtr += Length;\r
3074 if (*StringPtr == 0) {\r
3075 *Progress = StringPtr;\r
3076 break;\r
3077 }\r
3078\r
3079 StringPtr++;\r
93e3992d 3080 }\r
3081\r
84f9a9ec
LG
3082Done:\r
3083 if (EFI_ERROR (Status)) {\r
3084 FreePool (*Results);\r
6e3f5b2a 3085 *Results = NULL;\r
84f9a9ec
LG
3086 }\r
3087 \r
3088 if (ConfigRequest != NULL) {\r
3089 FreePool (ConfigRequest);\r
3090 }\r
3091 \r
3092 if (AccessResults != NULL) {\r
3093 FreePool (AccessResults);\r
3094 }\r
3095 \r
3096 if (DefaultResults != NULL) {\r
3097 FreePool (DefaultResults);\r
3098 }\r
3099 \r
3100 if (DevicePath != NULL) {\r
3101 FreePool (DevicePath);\r
3102 } \r
93e3992d 3103\r
84f9a9ec 3104 return Status;\r
93e3992d 3105}\r
3106\r
3107\r
3108/**\r
3109 This function allows the caller to request the current configuration for the\r
3110 entirety of the current HII database and returns the data in a\r
3111 null-terminated Unicode string.\r
3112\r
3113 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3114 instance.\r
3115 @param Results Null-terminated Unicode string in\r
3116 <MultiConfigAltResp> format which has all values\r
3117 filled in for the names in the Request string.\r
3118 String to be allocated by the called function.\r
3119 De-allocation is up to the caller.\r
3120\r
3121 @retval EFI_SUCCESS The Results string is filled with the values\r
3122 corresponding to all requested names.\r
3123 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3124 results that must be stored awaiting possible\r
3125 future protocols.\r
3126 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
3127 parameter would result in this type of error.\r
3128\r
3129**/\r
3130EFI_STATUS\r
3131EFIAPI\r
3132HiiConfigRoutingExportConfig (\r
3133 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3134 OUT EFI_STRING *Results\r
3135 )\r
3136{\r
93e3992d 3137 EFI_STATUS Status;\r
93e3992d 3138 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
3139 EFI_STRING AccessResults;\r
3140 EFI_STRING Progress;\r
6e3f5b2a 3141 EFI_STRING StringPtr;\r
ae79d2f9 3142 EFI_STRING ConfigRequest;\r
8d00a0f1 3143 UINTN Index;\r
3144 EFI_HANDLE *ConfigAccessHandles;\r
3145 UINTN NumberConfigAccessHandles;\r
3146 BOOLEAN FirstElement;\r
84f9a9ec
LG
3147 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3148 EFI_HII_HANDLE HiiHandle;\r
3149 EFI_STRING DefaultResults;\r
3150 HII_DATABASE_PRIVATE_DATA *Private;\r
3151 LIST_ENTRY *Link;\r
3152 HII_DATABASE_RECORD *Database;\r
3153 UINT8 *DevicePathPkg;\r
3154 UINT8 *CurrentDevicePath;\r
ae79d2f9 3155 BOOLEAN IfrDataParsedFlag;\r
93e3992d 3156\r
3157 if (This == NULL || Results == NULL) {\r
3158 return EFI_INVALID_PARAMETER;\r
3159 }\r
3160\r
84f9a9ec
LG
3161 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3162\r
93e3992d 3163 //\r
3164 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3165 // Results if this fix length is insufficient.\r
3166 //\r
3167 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3168 if (*Results == NULL) {\r
3169 return EFI_OUT_OF_RESOURCES;\r
3170 }\r
3171\r
8d00a0f1 3172 NumberConfigAccessHandles = 0;\r
3173 Status = gBS->LocateHandleBuffer (\r
3174 ByProtocol,\r
3175 &gEfiHiiConfigAccessProtocolGuid,\r
3176 NULL,\r
3177 &NumberConfigAccessHandles,\r
3178 &ConfigAccessHandles\r
3179 );\r
3180 if (EFI_ERROR (Status)) {\r
3181 return Status;\r
3182 }\r
93e3992d 3183\r
8d00a0f1 3184 FirstElement = TRUE;\r
93e3992d 3185\r
8d00a0f1 3186 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 3187 Status = gBS->HandleProtocol (\r
8d00a0f1 3188 ConfigAccessHandles[Index],\r
93e3992d 3189 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 3190 (VOID **) &ConfigAccess\r
93e3992d 3191 );\r
8d00a0f1 3192 if (EFI_ERROR (Status)) {\r
3193 continue;\r
3194 }\r
93e3992d 3195\r
84f9a9ec
LG
3196 //\r
3197 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
3198 //\r
ae79d2f9 3199 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
3200 Progress = NULL;\r
3201 HiiHandle = NULL;\r
84f9a9ec 3202 DefaultResults = NULL;\r
8567300a 3203 Database = NULL;\r
ae79d2f9 3204 ConfigRequest = NULL;\r
84f9a9ec 3205 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
3206 if (DevicePath != NULL) {\r
3207 for (Link = Private->DatabaseList.ForwardLink;\r
3208 Link != &Private->DatabaseList;\r
3209 Link = Link->ForwardLink\r
3210 ) {\r
3211 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3212 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3213 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3214 if (CompareMem (\r
84f9a9ec
LG
3215 DevicePath,\r
3216 CurrentDevicePath,\r
6e3f5b2a
LG
3217 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3218 ) == 0) {\r
84f9a9ec
LG
3219 HiiHandle = Database->Handle;\r
3220 break;\r
3221 }\r
3222 }\r
3223 }\r
3224 }\r
3225\r
93e3992d 3226 Status = ConfigAccess->ExtractConfig (\r
3227 ConfigAccess,\r
6e3f5b2a 3228 NULL,\r
84f9a9ec 3229 &Progress,\r
93e3992d 3230 &AccessResults\r
3231 );\r
ae79d2f9 3232 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
3233 //\r
3234 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3235 //\r
3236 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
3237 IfrDataParsedFlag = TRUE;\r
3238 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3239 //\r
3240 // Get the full request string to get the Current setting again.\r
3241 //\r
3242 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
3243 Status = ConfigAccess->ExtractConfig (\r
3244 ConfigAccess,\r
3245 ConfigRequest,\r
3246 &Progress,\r
3247 &AccessResults\r
3248 );\r
3249 FreePool (ConfigRequest);\r
3250 } else {\r
3251 Status = EFI_NOT_FOUND;\r
3252 }\r
3253 }\r
3254 }\r
3255\r
3256 if (!EFI_ERROR (Status)) {\r
3257 //\r
3258 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3259 //\r
3260 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
3261 StringPtr = StrStr (AccessResults, L"&GUID=");\r
3262 if (StringPtr != NULL) {\r
3263 *StringPtr = 0;\r
3264 }\r
3265 if (StrStr (AccessResults, L"&OFFSET=") != NULL) {\r
ae79d2f9
LG
3266 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
3267 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
3268 }\r
3269 if (StringPtr != NULL) {\r
3270 *StringPtr = L'&';\r
3271 }\r
3272 }\r
84f9a9ec
LG
3273 //\r
3274 // Merge the default sting from IFR code into the got setting from driver.\r
3275 //\r
3276 if (DefaultResults != NULL) {\r
8567300a
LG
3277 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3278 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 3279 FreePool (DefaultResults);\r
8567300a 3280 DefaultResults = NULL;\r
84f9a9ec
LG
3281 }\r
3282 \r
8d00a0f1 3283 //\r
3284 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3285 // which seperates the first <ConfigAltResp> and the following ones. \r
3286 //\r
3287 if (!FirstElement) {\r
3288 Status = AppendToMultiString (Results, L"&");\r
3289 ASSERT_EFI_ERROR (Status);\r
676df92c 3290 }\r
8d00a0f1 3291 \r
3292 Status = AppendToMultiString (Results, AccessResults);\r
3293 ASSERT_EFI_ERROR (Status);\r
93e3992d 3294\r
8d00a0f1 3295 FirstElement = FALSE;\r
3296 \r
3297 FreePool (AccessResults);\r
3298 AccessResults = NULL;\r
3299 }\r
93e3992d 3300 }\r
f4113e1f 3301 FreePool (ConfigAccessHandles);\r
93e3992d 3302\r
8d00a0f1 3303 return EFI_SUCCESS; \r
93e3992d 3304}\r
3305\r
3306\r
3307/**\r
3308 This function processes the results of processing forms and routes it to the\r
3309 appropriate handlers or storage.\r
3310\r
3311 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3312 instance.\r
3313 @param Configuration A null-terminated Unicode string in\r
3314 <MulltiConfigResp> format.\r
3315 @param Progress A pointer to a string filled in with the offset of\r
3316 the most recent & before the first failing name /\r
3317 value pair (or the beginning of the string if the\r
3318 failure is in the first name / value pair) or the\r
3319 terminating NULL if all was successful.\r
3320\r
3321 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
3322 distribution.\r
3323 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3324 results that must be stored awaiting possible\r
3325 future protocols.\r
3326 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
3327 would result in this type of error.\r
3328 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3329 found.\r
3330\r
3331**/\r
3332EFI_STATUS\r
3333EFIAPI\r
813acf3a 3334HiiConfigRoutingRouteConfig (\r
93e3992d 3335 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3336 IN CONST EFI_STRING Configuration,\r
3337 OUT EFI_STRING *Progress\r
3338 )\r
3339{\r
84f9a9ec 3340 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3341 EFI_STRING StringPtr;\r
3342 EFI_STRING ConfigResp;\r
3343 UINTN Length;\r
3344 EFI_STATUS Status;\r
3345 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 3346 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
3347 LIST_ENTRY *Link;\r
3348 HII_DATABASE_RECORD *Database;\r
3349 UINT8 *DevicePathPkg;\r
3350 UINT8 *CurrentDevicePath;\r
93e3992d 3351 EFI_HANDLE DriverHandle;\r
3352 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3353 EFI_STRING AccessProgress;\r
cce6230f
ED
3354 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
3355 BOOLEAN IsEfiVarstore;\r
93e3992d 3356\r
3357 if (This == NULL || Progress == NULL) {\r
3358 return EFI_INVALID_PARAMETER;\r
3359 }\r
3360\r
3361 if (Configuration == NULL) {\r
3362 *Progress = NULL;\r
3363 return EFI_INVALID_PARAMETER;\r
3364 }\r
3365\r
84f9a9ec 3366 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 3367 StringPtr = Configuration;\r
3368 *Progress = StringPtr;\r
cce6230f
ED
3369 Database = NULL;\r
3370 AccessProgress = NULL;\r
3371 EfiVarStoreInfo= NULL;\r
3372 IsEfiVarstore = FALSE;\r
93e3992d 3373\r
3374 //\r
3375 // The first element of <MultiConfigResp> should be\r
3376 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
3377 //\r
3378 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3379 return EFI_INVALID_PARAMETER;\r
3380 }\r
3381\r
3382 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
3383 //\r
3384 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
3385 // or most recent & before the error.\r
3386 //\r
3387 if (StringPtr == Configuration) {\r
3388 *Progress = StringPtr;\r
3389 } else {\r
3390 *Progress = StringPtr - 1;\r
3391 }\r
3392\r
3393 //\r
3394 // Process each <ConfigResp> of <MultiConfigResp>\r
3395 //\r
3396 Length = CalculateConfigStringLen (StringPtr);\r
3397 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
3398 if (ConfigResp == NULL) {\r
3399 return EFI_OUT_OF_RESOURCES;\r
3400 }\r
3401 //\r
3402 // Append '\0' to the end of ConfigRequest\r
3403 //\r
3404 *(ConfigResp + Length) = 0;\r
3405\r
3406 //\r
3407 // Get the UEFI device path\r
3408 //\r
3409 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
3410 if (EFI_ERROR (Status)) {\r
676df92c 3411 FreePool (ConfigResp);\r
93e3992d 3412 return Status;\r
3413 }\r
3414\r
3415 //\r
84f9a9ec
LG
3416 // Find driver which matches the routing data.\r
3417 //\r
3418 DriverHandle = NULL;\r
84f9a9ec
LG
3419 for (Link = Private->DatabaseList.ForwardLink;\r
3420 Link != &Private->DatabaseList;\r
3421 Link = Link->ForwardLink\r
3422 ) {\r
3423 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3424\r
3425 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3426 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 3427 if (CompareMem (\r
84f9a9ec
LG
3428 DevicePath,\r
3429 CurrentDevicePath,\r
6e3f5b2a
LG
3430 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
3431 ) == 0) {\r
84f9a9ec
LG
3432 DriverHandle = Database->DriverHandle;\r
3433 break;\r
3434 }\r
3435 }\r
3436 }\r
93e3992d 3437\r
84f9a9ec
LG
3438 //\r
3439 // Try to find driver handle by device path.\r
3440 //\r
3441 if (DriverHandle == NULL) {\r
3442 TempDevicePath = DevicePath;\r
3443 Status = gBS->LocateDevicePath (\r
3444 &gEfiDevicePathProtocolGuid,\r
3445 &TempDevicePath,\r
3446 &DriverHandle\r
3447 );\r
3448 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
3449 //\r
3450 // Routing data does not match any known driver.\r
3451 // Set Progress to the 'G' in "GUID" of the routing header.\r
3452 //\r
3453 FreePool (DevicePath);\r
3454 *Progress = StringPtr;\r
3455 FreePool (ConfigResp);\r
3456 return EFI_NOT_FOUND;\r
3457 }\r
93e3992d 3458 }\r
3459\r
84f9a9ec
LG
3460 FreePool (DevicePath);\r
3461\r
93e3992d 3462 //\r
cce6230f 3463 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 3464 //\r
cce6230f
ED
3465 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
3466 if (EFI_ERROR (Status)) {\r
3467 return Status;\r
3468 }\r
93e3992d 3469\r
cce6230f
ED
3470 if (IsEfiVarstore) {\r
3471 //\r
3472 // Call the SetVariable function to route settings.\r
3473 // \r
3474 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
3475 FreePool (EfiVarStoreInfo);\r
3476 } else {\r
3477 //\r
3478 // Call corresponding ConfigAccess protocol to route settings\r
3479 //\r
3480 Status = gBS->HandleProtocol (\r
3481 DriverHandle,\r
3482 &gEfiHiiConfigAccessProtocolGuid,\r
3483 (VOID **) &ConfigAccess\r
3484 );\r
3485 ASSERT_EFI_ERROR (Status);\r
93e3992d 3486\r
cce6230f
ED
3487 Status = ConfigAccess->RouteConfig (\r
3488 ConfigAccess,\r
3489 ConfigResp,\r
3490 &AccessProgress\r
3491 );\r
3492 }\r
93e3992d 3493 if (EFI_ERROR (Status)) {\r
3494 //\r
3495 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
3496 // Map it to the progress on <MultiConfigResp> then return it.\r
3497 //\r
8d00a0f1 3498 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 3499\r
676df92c 3500 FreePool (ConfigResp);\r
93e3992d 3501 return Status;\r
3502 }\r
3503\r
676df92c 3504 FreePool (ConfigResp);\r
93e3992d 3505 ConfigResp = NULL;\r
3506\r
3507 //\r
3508 // Go to next <ConfigResp> (skip '&').\r
3509 //\r
3510 StringPtr += Length;\r
3511 if (*StringPtr == 0) {\r
3512 *Progress = StringPtr;\r
3513 break;\r
3514 }\r
3515\r
3516 StringPtr++;\r
3517\r
3518 }\r
3519\r
3520 return EFI_SUCCESS;\r
93e3992d 3521}\r
3522\r
3523\r
3524/**\r
3525 This helper function is to be called by drivers to map configuration data\r
3526 stored in byte array ("block") formats such as UEFI Variables into current\r
3527 configuration strings.\r
3528\r
3529 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3530 instance.\r
3531 @param ConfigRequest A null-terminated Unicode string in\r
3532 <ConfigRequest> format.\r
3533 @param Block Array of bytes defining the block's configuration.\r
3534 @param BlockSize Length in bytes of Block.\r
3535 @param Config Filled-in configuration string. String allocated\r
3536 by the function. Returned only if call is\r
84f9a9ec 3537 successful. It is <ConfigResp> string format.\r
93e3992d 3538 @param Progress A pointer to a string filled in with the offset of\r
3539 the most recent & before the first failing\r
3540 name/value pair (or the beginning of the string if\r
3541 the failure is in the first name / value pair) or\r
3542 the terminating NULL if all was successful.\r
3543\r
3544 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
3545 terminator at the end of the ConfigRequest\r
3546 string.\r
3547 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
3548 points to the first character of ConfigRequest.\r
3549 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
3550 Block parameter would result in this type of\r
3551 error. Progress points to the first character of\r
3552 ConfigRequest.\r
3553 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
3554 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
3555 Block is left updated and Progress points at\r
3556 the "&" preceding the first non-<BlockName>.\r
3557\r
3558**/\r
3559EFI_STATUS\r
3560EFIAPI\r
3561HiiBlockToConfig (\r
3562 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3563 IN CONST EFI_STRING ConfigRequest,\r
3564 IN CONST UINT8 *Block,\r
3565 IN CONST UINTN BlockSize,\r
3566 OUT EFI_STRING *Config,\r
3567 OUT EFI_STRING *Progress\r
3568 )\r
3569{\r
84f9a9ec 3570 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 3571 EFI_STRING StringPtr;\r
3572 UINTN Length;\r
3573 EFI_STATUS Status;\r
3574 EFI_STRING TmpPtr;\r
3575 UINT8 *TmpBuffer;\r
3576 UINTN Offset;\r
3577 UINTN Width;\r
3578 UINT8 *Value;\r
3579 EFI_STRING ValueStr;\r
3580 EFI_STRING ConfigElement;\r
63d55bb9
LG
3581 UINTN Index;\r
3582 UINT8 *TemBuffer;\r
3583 CHAR16 *TemString;\r
41ff10dc 3584 CHAR16 TemChar;\r
93e3992d 3585\r
3586 if (This == NULL || Progress == NULL || Config == NULL) {\r
3587 return EFI_INVALID_PARAMETER;\r
3588 }\r
3589\r
3590 if (Block == NULL || ConfigRequest == NULL) {\r
3591 *Progress = ConfigRequest;\r
3592 return EFI_INVALID_PARAMETER;\r
3593 }\r
3594\r
84f9a9ec
LG
3595\r
3596 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3597 ASSERT (Private != NULL);\r
3598\r
93e3992d 3599 StringPtr = ConfigRequest;\r
3600 ValueStr = NULL;\r
3601 Value = NULL;\r
3602 ConfigElement = NULL;\r
3603\r
3604 //\r
3605 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3606 // Results if this fix length is insufficient.\r
3607 //\r
3608 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3609 if (*Config == NULL) {\r
3610 return EFI_OUT_OF_RESOURCES;\r
3611 }\r
3612\r
3613 //\r
3614 // Jump <ConfigHdr>\r
3615 //\r
3616 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3617 *Progress = StringPtr;\r
3618 Status = EFI_INVALID_PARAMETER;\r
3619 goto Exit;\r
3620 }\r
3621 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
3622 StringPtr++;\r
3623 }\r
3624 if (*StringPtr == 0) {\r
76c24251 3625 *Progress = StringPtr - 1;\r
93e3992d 3626 Status = EFI_INVALID_PARAMETER;\r
3627 goto Exit;\r
3628 }\r
08e6463a 3629\r
3630 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3631 StringPtr++;\r
3632 }\r
3633 if (*StringPtr == 0) {\r
41ff10dc
ED
3634 *Progress = StringPtr;\r
3635 Status = EFI_SUCCESS;\r
3636\r
3637 AppendToMultiString(Config, ConfigRequest);\r
3638 HiiToLower (*Config);\r
3639\r
08e6463a 3640 goto Exit;\r
3641 }\r
3642 //\r
3643 // Skip '&'\r
3644 //\r
3645 StringPtr++;\r
93e3992d 3646\r
3647 //\r
3648 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
3649 //\r
41ff10dc
ED
3650 TemChar = *StringPtr;\r
3651 *StringPtr = '\0';\r
3652 AppendToMultiString(Config, ConfigRequest);\r
3653 *StringPtr = TemChar;\r
93e3992d 3654\r
3655 //\r
3656 // Parse each <RequestElement> if exists\r
3657 // Only <BlockName> format is supported by this help function.\r
3658 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
3659 //\r
3660 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
3661 //\r
3662 // Back up the header of one <BlockName>\r
3663 //\r
3664 TmpPtr = StringPtr;\r
3665\r
3666 StringPtr += StrLen (L"OFFSET=");\r
3667 //\r
3668 // Get Offset\r
3669 //\r
3670 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 3671 if (EFI_ERROR (Status)) {\r
93e3992d 3672 *Progress = ConfigRequest;\r
3673 goto Exit;\r
3674 }\r
3675 Offset = 0;\r
3676 CopyMem (\r
3677 &Offset,\r
3678 TmpBuffer,\r
3679 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3680 );\r
676df92c 3681 FreePool (TmpBuffer);\r
93e3992d 3682\r
3683 StringPtr += Length;\r
3684 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3685 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
3686 Status = EFI_INVALID_PARAMETER;\r
3687 goto Exit;\r
3688 }\r
3689 StringPtr += StrLen (L"&WIDTH=");\r
3690\r
3691 //\r
3692 // Get Width\r
3693 //\r
3694 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 3695 if (EFI_ERROR (Status)) {\r
93e3992d 3696 *Progress = ConfigRequest;\r
3697 goto Exit;\r
3698 }\r
3699 Width = 0;\r
3700 CopyMem (\r
3701 &Width,\r
3702 TmpBuffer,\r
3703 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3704 );\r
676df92c 3705 FreePool (TmpBuffer);\r
93e3992d 3706\r
3707 StringPtr += Length;\r
3708 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3709 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3710 Status = EFI_INVALID_PARAMETER;\r
3711 goto Exit;\r
3712 }\r
3713\r
3714 //\r
3715 // Calculate Value and convert it to hex string.\r
3716 //\r
3717 if (Offset + Width > BlockSize) {\r
3718 *Progress = StringPtr;\r
3719 Status = EFI_DEVICE_ERROR;\r
3720 goto Exit;\r
3721 }\r
3722\r
3723 Value = (UINT8 *) AllocateZeroPool (Width);\r
3724 if (Value == NULL) {\r
3725 *Progress = ConfigRequest;\r
3726 Status = EFI_OUT_OF_RESOURCES;\r
3727 goto Exit;\r
3728 }\r
3729\r
3730 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
3731\r
3732 Length = Width * 2 + 1;\r
3733 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
3734 if (ValueStr == NULL) {\r
3735 *Progress = ConfigRequest;\r
3736 Status = EFI_OUT_OF_RESOURCES;\r
3737 goto Exit;\r
3738 }\r
63d55bb9
LG
3739 \r
3740 TemString = ValueStr;\r
3741 TemBuffer = Value + Width - 1;\r
3742 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
3743 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
3744 }\r
813acf3a 3745\r
676df92c 3746 FreePool (Value);\r
93e3992d 3747 Value = NULL;\r
3748\r
3749 //\r
3750 // Build a ConfigElement\r
3751 //\r
3752 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
3753 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
3754 if (ConfigElement == NULL) {\r
3755 Status = EFI_OUT_OF_RESOURCES;\r
3756 goto Exit;\r
3757 }\r
3758 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
3759 if (*StringPtr == 0) {\r
3760 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
3761 }\r
3762 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
3763 StrCat (ConfigElement, L"VALUE=");\r
3764 StrCat (ConfigElement, ValueStr);\r
3765\r
3766 AppendToMultiString (Config, ConfigElement);\r
3767\r
676df92c 3768 FreePool (ConfigElement);\r
3769 FreePool (ValueStr);\r
93e3992d 3770 ConfigElement = NULL;\r
3771 ValueStr = NULL;\r
3772\r
3773 //\r
3774 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
3775 //\r
3776 if (*StringPtr == 0) {\r
3777 break;\r
3778 }\r
3779 AppendToMultiString (Config, L"&");\r
3780 StringPtr++;\r
3781\r
3782 }\r
3783\r
3784 if (*StringPtr != 0) {\r
3785 *Progress = StringPtr - 1;\r
3786 Status = EFI_INVALID_PARAMETER;\r
3787 goto Exit;\r
3788 }\r
84f9a9ec
LG
3789 \r
3790 HiiToLower (*Config);\r
93e3992d 3791 *Progress = StringPtr;\r
3792 return EFI_SUCCESS;\r
3793\r
3794Exit:\r
76c24251 3795 if (*Config != NULL) {\r
1f1cb2f2
LG
3796 FreePool (*Config);\r
3797 *Config = NULL;\r
76c24251 3798 }\r
676df92c 3799 if (ValueStr != NULL) {\r
3800 FreePool (ValueStr);\r
3801 }\r
3802 if (Value != NULL) {\r
3803 FreePool (Value);\r
3804 }\r
69367b5b 3805 if (ConfigElement != NULL) {\r
676df92c 3806 FreePool (ConfigElement);\r
3807 }\r
93e3992d 3808\r
3809 return Status;\r
3810\r
3811}\r
3812\r
3813\r
3814/**\r
3815 This helper function is to be called by drivers to map configuration strings\r
3816 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
3817\r
3818 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3819 instance.\r
3820 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 3821 format.\r
93e3992d 3822 @param Block A possibly null array of bytes representing the\r
3823 current block. Only bytes referenced in the\r
3824 ConfigResp string in the block are modified. If\r
3825 this parameter is null or if the *BlockSize\r
3826 parameter is (on input) shorter than required by\r
3827 the Configuration string, only the BlockSize\r
3828 parameter is updated and an appropriate status\r
3829 (see below) is returned.\r
3830 @param BlockSize The length of the Block in units of UINT8. On\r
3831 input, this is the size of the Block. On output,\r
3832 if successful, contains the index of the last\r
3833 modified byte in the Block.\r
3834 @param Progress On return, points to an element of the ConfigResp\r
3835 string filled in with the offset of the most\r
3836 recent '&' before the first failing name / value\r
3837 pair (or the beginning of the string if the\r
3838 failure is in the first name / value pair) or the\r
3839 terminating NULL if all was successful.\r
3840\r
3841 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
3842 terminator at the end of the ConfigResp string.\r
3843 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
3844 points to the first character of ConfigResp.\r
3845 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
3846 Block parameter would result in this type of\r
3847 error. Progress points to the first character of\r
3848 ConfigResp.\r
3849 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
3850 value pair. Block is left updated and\r
3851 Progress points at the '&' preceding the first\r
3852 non-<BlockName>.\r
09b79417
LG
3853 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
3854 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
3855 Progress points to the "G" in "GUID" of the errant\r
3856 routing data.\r
93e3992d 3857\r
3858**/\r
3859EFI_STATUS\r
3860EFIAPI\r
3861HiiConfigToBlock (\r
3862 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3863 IN CONST EFI_STRING ConfigResp,\r
3864 IN OUT UINT8 *Block,\r
3865 IN OUT UINTN *BlockSize,\r
3866 OUT EFI_STRING *Progress\r
3867 )\r
3868{\r
3869 HII_DATABASE_PRIVATE_DATA *Private;\r
3870 EFI_STRING StringPtr;\r
3871 UINTN Length;\r
3872 EFI_STATUS Status;\r
3873 UINT8 *TmpBuffer;\r
3874 UINTN Offset;\r
3875 UINTN Width;\r
3876 UINT8 *Value;\r
3877 UINTN BufferSize;\r
09b79417 3878 UINTN MaxBlockSize;\r
93e3992d 3879\r
3880 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
3881 return EFI_INVALID_PARAMETER;\r
3882 }\r
3883\r
09b79417
LG
3884 *Progress = ConfigResp;\r
3885 if (ConfigResp == NULL) {\r
93e3992d 3886 return EFI_INVALID_PARAMETER;\r
3887 }\r
3888\r
3889 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3890 ASSERT (Private != NULL);\r
3891\r
3892 StringPtr = ConfigResp;\r
3893 BufferSize = *BlockSize;\r
3894 Value = NULL;\r
09b79417 3895 MaxBlockSize = 0;\r
93e3992d 3896\r
3897 //\r
3898 // Jump <ConfigHdr>\r
3899 //\r
3900 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3901 *Progress = StringPtr;\r
3902 Status = EFI_INVALID_PARAMETER;\r
3903 goto Exit;\r
3904 }\r
3905 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
3906 StringPtr++;\r
3907 }\r
3908 if (*StringPtr == 0) {\r
3909 *Progress = StringPtr;\r
3910 Status = EFI_INVALID_PARAMETER;\r
3911 goto Exit;\r
3912 }\r
08e6463a 3913\r
3914 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3915 StringPtr++;\r
3916 }\r
3917 if (*StringPtr == 0) {\r
3918 *Progress = StringPtr;\r
3919 Status = EFI_INVALID_PARAMETER;\r
3920 goto Exit;\r
3921 }\r
93e3992d 3922\r
3923 //\r
3924 // Parse each <ConfigElement> if exists\r
edae8d2d 3925 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 3926 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
3927 //\r
edae8d2d
ED
3928 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
3929 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 3930 //\r
3931 // Get Offset\r
3932 //\r
3933 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 3934 if (EFI_ERROR (Status)) {\r
93e3992d 3935 *Progress = ConfigResp;\r
3936 goto Exit;\r
3937 }\r
3938 Offset = 0;\r
3939 CopyMem (\r
3940 &Offset,\r
3941 TmpBuffer,\r
3942 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3943 );\r
676df92c 3944 FreePool (TmpBuffer);\r
93e3992d 3945\r
3946 StringPtr += Length;\r
3947 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
edae8d2d 3948 *Progress = StringPtr - Length - StrLen (L"&OFFSET=");\r
93e3992d 3949 Status = EFI_INVALID_PARAMETER;\r
3950 goto Exit;\r
3951 }\r
3952 StringPtr += StrLen (L"&WIDTH=");\r
3953\r
3954 //\r
3955 // Get Width\r
3956 //\r
3957 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 3958 if (EFI_ERROR (Status)) {\r
93e3992d 3959 *Progress = ConfigResp;\r
3960 goto Exit;\r
3961 }\r
3962 Width = 0;\r
3963 CopyMem (\r
3964 &Width,\r
3965 TmpBuffer,\r
3966 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3967 );\r
676df92c 3968 FreePool (TmpBuffer);\r
93e3992d 3969\r
3970 StringPtr += Length;\r
3971 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
3972 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3973 Status = EFI_INVALID_PARAMETER;\r
3974 goto Exit;\r
3975 }\r
3976 StringPtr += StrLen (L"&VALUE=");\r
3977\r
3978 //\r
3979 // Get Value\r
3980 //\r
3981 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 3982 if (EFI_ERROR (Status)) {\r
93e3992d 3983 *Progress = ConfigResp;\r
3984 goto Exit;\r
3985 }\r
3986\r
3987 StringPtr += Length;\r
3988 if (*StringPtr != 0 && *StringPtr != L'&') {\r
edae8d2d 3989 *Progress = StringPtr - Length - StrLen (L"&VALUE=");\r
93e3992d 3990 Status = EFI_INVALID_PARAMETER;\r
3991 goto Exit;\r
3992 }\r
3993\r
3994 //\r
3995 // Update the Block with configuration info\r
3996 //\r
09b79417
LG
3997 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
3998 CopyMem (Block + Offset, Value, Width);\r
3999 }\r
4000 if (Offset + Width > MaxBlockSize) {\r
4001 MaxBlockSize = Offset + Width;\r
93e3992d 4002 }\r
93e3992d 4003\r
676df92c 4004 FreePool (Value);\r
93e3992d 4005 Value = NULL;\r
4006\r
4007 //\r
edae8d2d 4008 // If '\0', parsing is finished.\r
93e3992d 4009 //\r
4010 if (*StringPtr == 0) {\r
4011 break;\r
4012 }\r
93e3992d 4013 }\r
84f9a9ec
LG
4014 \r
4015 //\r
edae8d2d 4016 // The input string is not ConfigResp format, return error.\r
84f9a9ec 4017 //\r
edae8d2d
ED
4018 if (*StringPtr != 0) {\r
4019 *Progress = StringPtr;\r
93e3992d 4020 Status = EFI_INVALID_PARAMETER;\r
4021 goto Exit;\r
4022 }\r
4023\r
6e3f5b2a 4024 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
4025 *BlockSize = MaxBlockSize - 1;\r
4026\r
4027 if (MaxBlockSize > BufferSize) {\r
4028 *BlockSize = MaxBlockSize;\r
9ac0640d 4029 if (Block != NULL) {\r
09b79417
LG
4030 return EFI_DEVICE_ERROR;\r
4031 }\r
4032 }\r
4033\r
9ac0640d
LG
4034 if (Block == NULL) {\r
4035 *Progress = ConfigResp;\r
4036 return EFI_INVALID_PARAMETER;\r
4037 }\r
4038\r
93e3992d 4039 return EFI_SUCCESS;\r
4040\r
4041Exit:\r
4042\r
676df92c 4043 if (Value != NULL) {\r
4044 FreePool (Value);\r
4045 }\r
93e3992d 4046 return Status;\r
4047}\r
4048\r
4049\r
4050/**\r
4051 This helper function is to be called by drivers to extract portions of\r
4052 a larger configuration string.\r
4053\r
4054 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4055 instance.\r
4056 @param Configuration A null-terminated Unicode string in\r
771ececd 4057 <MultiConfigAltResp> format.\r
93e3992d 4058 @param Guid A pointer to the GUID value to search for in the\r
4059 routing portion of the ConfigResp string when\r
4060 retrieving the requested data. If Guid is NULL,\r
4061 then all GUID values will be searched for.\r
4062 @param Name A pointer to the NAME value to search for in the\r
4063 routing portion of the ConfigResp string when\r
4064 retrieving the requested data. If Name is NULL,\r
4065 then all Name values will be searched for.\r
4066 @param DevicePath A pointer to the PATH value to search for in the\r
4067 routing portion of the ConfigResp string when\r
4068 retrieving the requested data. If DevicePath is\r
4069 NULL, then all DevicePath values will be searched\r
4070 for.\r
4071 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
4072 routing portion of the ConfigResp string when\r
4073 retrieving the requested data. If this parameter\r
4074 is NULL, then the current setting will be\r
4075 retrieved.\r
4076 @param AltCfgResp A pointer to a buffer which will be allocated by\r
4077 the function which contains the retrieved string\r
4078 as requested. This buffer is only allocated if\r
84f9a9ec 4079 the call was successful. It is <ConfigResp> format.\r
93e3992d 4080\r
4081 @retval EFI_SUCCESS The request succeeded. The requested data was\r
4082 extracted and placed in the newly allocated\r
4083 AltCfgResp buffer.\r
4084 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
4085 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
4086 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4087 found.\r
4088\r
4089**/\r
4090EFI_STATUS\r
4091EFIAPI\r
4092HiiGetAltCfg (\r
4093 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4094 IN CONST EFI_STRING Configuration,\r
4095 IN CONST EFI_GUID *Guid,\r
4096 IN CONST EFI_STRING Name,\r
4097 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4098 IN CONST UINT16 *AltCfgId,\r
4099 OUT EFI_STRING *AltCfgResp\r
4100 )\r
4101{\r
93e3992d 4102 EFI_STATUS Status;\r
4103 EFI_STRING StringPtr;\r
e90b081a 4104 EFI_STRING HdrStart;\r
4105 EFI_STRING HdrEnd;\r
93e3992d 4106 EFI_STRING TmpPtr;\r
4107 UINTN Length;\r
e90b081a 4108 EFI_STRING GuidStr;\r
4109 EFI_STRING NameStr;\r
4110 EFI_STRING PathStr;\r
4111 EFI_STRING AltIdStr;\r
4112 EFI_STRING Result;\r
4113 BOOLEAN GuidFlag;\r
4114 BOOLEAN NameFlag;\r
4115 BOOLEAN PathFlag;\r
4116\r
4117 HdrStart = NULL;\r
4118 HdrEnd = NULL;\r
4119 GuidStr = NULL;\r
4120 NameStr = NULL;\r
4121 PathStr = NULL;\r
4122 AltIdStr = NULL;\r
4123 Result = NULL;\r
4124 GuidFlag = FALSE;\r
4125 NameFlag = FALSE;\r
4126 PathFlag = FALSE;\r
93e3992d 4127\r
4128 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
4129 return EFI_INVALID_PARAMETER;\r
4130 }\r
4131\r
4132 StringPtr = Configuration;\r
4133 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4134 return EFI_INVALID_PARAMETER;\r
4135 }\r
4136\r
4137 //\r
4138 // Generate the sub string for later matching.\r
4139 //\r
813acf3a 4140 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 4141 GenerateSubStr (\r
4142 L"PATH=",\r
4143 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 4144 (VOID *) DevicePath,\r
4145 1,\r
93e3992d 4146 &PathStr\r
4147 );\r
4148 if (AltCfgId != NULL) {\r
813acf3a 4149 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 4150 }\r
4151 if (Name != NULL) {\r
813acf3a 4152 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 4153 } else {\r
813acf3a 4154 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 4155 }\r
4156\r
4157 while (*StringPtr != 0) {\r
4158 //\r
4159 // Try to match the GUID\r
4160 //\r
4161 if (!GuidFlag) {\r
4162 TmpPtr = StrStr (StringPtr, GuidStr);\r
4163 if (TmpPtr == NULL) {\r
4164 Status = EFI_NOT_FOUND;\r
4165 goto Exit;\r
4166 }\r
4167 HdrStart = TmpPtr;\r
4168\r
4169 //\r
4170 // Jump to <NameHdr>\r
4171 //\r
4172 if (Guid != NULL) {\r
4173 StringPtr = TmpPtr + StrLen (GuidStr);\r
4174 } else {\r
4175 StringPtr = StrStr (TmpPtr, L"NAME=");\r
4176 if (StringPtr == NULL) {\r
4177 Status = EFI_NOT_FOUND;\r
4178 goto Exit;\r
4179 }\r
4180 }\r
4181 GuidFlag = TRUE;\r
4182 }\r
4183\r
4184 //\r
4185 // Try to match the NAME\r
4186 //\r
4187 if (GuidFlag && !NameFlag) {\r
4188 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
4189 GuidFlag = FALSE;\r
4190 } else {\r
4191 //\r
4192 // Jump to <PathHdr>\r
4193 //\r
4194 if (Name != NULL) {\r
4195 StringPtr += StrLen (NameStr);\r
4196 } else {\r
4197 StringPtr = StrStr (StringPtr, L"PATH=");\r
4198 if (StringPtr == NULL) {\r
4199 Status = EFI_NOT_FOUND;\r
4200 goto Exit;\r
4201 }\r
4202 }\r
4203 NameFlag = TRUE;\r
4204 }\r
4205 }\r
4206\r
4207 //\r
4208 // Try to match the DevicePath\r
4209 //\r
4210 if (GuidFlag && NameFlag && !PathFlag) {\r
4211 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
4212 GuidFlag = FALSE;\r
4213 NameFlag = FALSE;\r
4214 } else {\r
4215 //\r
4216 // Jump to '&' before <DescHdr> or <ConfigBody>\r
4217 //\r
4218 if (DevicePath != NULL) {\r
4219 StringPtr += StrLen (PathStr);\r
4220 } else {\r
4221 StringPtr = StrStr (StringPtr, L"&");\r
4222 if (StringPtr == NULL) {\r
4223 Status = EFI_NOT_FOUND;\r
4224 goto Exit;\r
4225 }\r
84f9a9ec 4226 StringPtr ++;\r
93e3992d 4227 }\r
4228 PathFlag = TRUE;\r
84f9a9ec 4229 HdrEnd = StringPtr;\r
93e3992d 4230 }\r
4231 }\r
4232\r
4233 //\r
4234 // Try to match the AltCfgId\r
4235 //\r
4236 if (GuidFlag && NameFlag && PathFlag) {\r
4237 if (AltCfgId == NULL) {\r
4238 //\r
4239 // Return Current Setting when AltCfgId is NULL.\r
4240 //\r
4241 Status = OutputConfigBody (StringPtr, &Result);\r
4242 goto Exit;\r
4243 }\r
4244 //\r
4245 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
4246 //\r
4247 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
4248 GuidFlag = FALSE;\r
4249 NameFlag = FALSE;\r
4250 PathFlag = FALSE;\r
4251 } else {\r
84f9a9ec
LG
4252 //\r
4253 // Skip AltIdStr and &\r
4254 //\r
4255 StringPtr = StringPtr + StrLen (AltIdStr);\r
4256 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 4257 goto Exit;\r
4258 }\r
4259 }\r
4260 }\r
4261\r
4262 Status = EFI_NOT_FOUND;\r
4263\r
4264Exit:\r
76c24251 4265 *AltCfgResp = NULL;\r
bc166db3 4266 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 4267 //\r
4268 // Copy the <ConfigHdr> and <ConfigBody>\r
4269 //\r
84f9a9ec 4270 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 4271 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
4272 if (*AltCfgResp == NULL) {\r
4273 Status = EFI_OUT_OF_RESOURCES;\r
4274 } else {\r
4275 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
4276 StrCat (*AltCfgResp, Result);\r
4277 Status = EFI_SUCCESS;\r
4278 }\r
4279 }\r
4280\r
676df92c 4281 if (GuidStr != NULL) {\r
4282 FreePool (GuidStr);\r
4283 }\r
4284 if (NameStr != NULL) {\r
4285 FreePool (NameStr);\r
4286 }\r
4287 if (PathStr != NULL) {\r
4288 FreePool (PathStr);\r
4289 }\r
4290 if (AltIdStr != NULL) {\r
4291 FreePool (AltIdStr);\r
4292 }\r
4293 if (Result != NULL) {\r
4294 FreePool (Result);\r
4295 }\r
93e3992d 4296\r
4297 return Status;\r
4298\r
93e3992d 4299}\r
4300\r
36fe40c2 4301\r