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