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