Roll back changes to apply GetBestLanguage() in HiiDataBase. Exact language match...
[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
84f9a9ec 4Copyright (c) 2007 - 2008, Intel Corporation\r
93e3992d 5All rights reserved. This program and the accompanying materials\r
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
171 @param Str String to be converted\r
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
456 ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
457 ASSERT (*StringPtr != L'\0');\r
458\r
459 Buf = NULL;\r
460\r
461 TmpPtr = StringPtr;\r
462 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
463 StringPtr++;\r
464 }\r
465 *Len = StringPtr - TmpPtr;\r
466 Length = *Len + 1;\r
467\r
468 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
469 if (Str == NULL) {\r
470 Status = EFI_OUT_OF_RESOURCES;\r
471 goto Exit;\r
472 }\r
473 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
474 *(Str + *Len) = L'\0';\r
475\r
476 Length = (Length + 1) / 2;\r
477 Buf = (UINT8 *) AllocateZeroPool (Length);\r
478 if (Buf == NULL) {\r
479 Status = EFI_OUT_OF_RESOURCES;\r
480 goto Exit;\r
481 }\r
482 \r
483 Length = *Len;\r
484 ZeroMem (TemStr, sizeof (TemStr));\r
485 for (Index = 0; Index < Length; Index ++) {\r
486 TemStr[0] = Str[Length - Index - 1];\r
487 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
488 if ((Index & 1) == 0) {\r
489 Buf [Index/2] = DigitUint8;\r
490 } else {\r
491 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
492 }\r
493 }\r
494\r
495 *Number = Buf;\r
496 Status = EFI_SUCCESS;\r
497\r
498Exit:\r
499 if (Str != NULL) {\r
500 FreePool (Str);\r
501 }\r
502\r
503 return Status;\r
504}\r
505\r
506/**\r
507 This function merges DefaultAltCfgResp string into AltCfgResp string for\r
508 the missing AltCfgId in AltCfgResq.\r
509\r
510 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
511 <ConfigAltResp> format. The default value string \r
512 will be merged into it. \r
513 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
514 <MultiConfigAltResp> format. The default value \r
515 string may contain more than one ConfigAltResp\r
516 string for the different varstore buffer.\r
517\r
518 @retval EFI_SUCCESS The merged string returns.\r
519 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
520**/\r
521EFI_STATUS\r
522EFIAPI\r
523MergeDefaultString (\r
524 IN OUT EFI_STRING *AltCfgResp,\r
525 IN EFI_STRING DefaultAltCfgResp\r
526 )\r
527{\r
528 EFI_STRING StringPtrDefault;\r
529 EFI_STRING StringPtrEnd;\r
530 CHAR16 TempChar;\r
531 EFI_STRING StringPtr;\r
532 EFI_STRING AltConfigHdr;\r
533 UINTN HeaderLength;\r
534 UINTN SizeAltCfgResp;\r
535 \r
536 if (*AltCfgResp == NULL) {\r
537 return EFI_INVALID_PARAMETER;\r
538 }\r
539 \r
540 //\r
541 // Get the requestr ConfigHdr\r
542 //\r
543 SizeAltCfgResp = 0;\r
544 StringPtr = *AltCfgResp;\r
545 \r
546 //\r
547 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
548 //\r
549 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
550 return EFI_INVALID_PARAMETER;\r
551 }\r
552 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
553 StringPtr++;\r
554 }\r
555 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
556 StringPtr++;\r
557 }\r
558 if (*StringPtr == L'\0') {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
561 StringPtr += StrLen (L"&PATH=");\r
562 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
563 StringPtr ++;\r
564 }\r
565 HeaderLength = StringPtr - *AltCfgResp;\r
566\r
567 //\r
568 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
569 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
570 //\r
571 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));\r
572 if (AltConfigHdr == NULL) {\r
573 return EFI_OUT_OF_RESOURCES;\r
574 }\r
575 StrCpy (AltConfigHdr, L"&");\r
576 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);\r
577 StrCat (AltConfigHdr, L"&ALTCFG=");\r
578 HeaderLength = StrLen (AltConfigHdr);\r
579 \r
580 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
581 while (StringPtrDefault != NULL) {\r
582 //\r
583 // Get AltCfg Name\r
584 //\r
585 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);\r
586 StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
587 \r
588 //\r
589 // Append the found default value string to the input AltCfgResp\r
590 // \r
591 if (StringPtr == NULL) {\r
592 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
593 SizeAltCfgResp = StrSize (*AltCfgResp);\r
594 if (StringPtrEnd == NULL) {\r
595 //\r
596 // No more default string is found.\r
597 //\r
598 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
599 SizeAltCfgResp,\r
600 SizeAltCfgResp + StrSize (StringPtrDefault),\r
601 (VOID *) (*AltCfgResp)\r
602 );\r
8567300a
LG
603 if (*AltCfgResp == NULL) {\r
604 FreePool (AltConfigHdr);\r
605 return EFI_OUT_OF_RESOURCES;\r
606 }\r
84f9a9ec
LG
607 StrCat (*AltCfgResp, StringPtrDefault);\r
608 break;\r
609 } else {\r
610 TempChar = *StringPtrEnd;\r
611 *StringPtrEnd = L'\0';\r
612 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
613 SizeAltCfgResp,\r
614 SizeAltCfgResp + StrSize (StringPtrDefault),\r
615 (VOID *) (*AltCfgResp)\r
616 );\r
6e3f5b2a
LG
617 if (*AltCfgResp == NULL) {\r
618 FreePool (AltConfigHdr);\r
619 return EFI_OUT_OF_RESOURCES;\r
620 }\r
84f9a9ec
LG
621 StrCat (*AltCfgResp, StringPtrDefault);\r
622 *StringPtrEnd = TempChar;\r
623 }\r
624 }\r
625 \r
626 //\r
627 // Find next AltCfg String\r
8567300a 628 //\r
84f9a9ec
LG
629 *(AltConfigHdr + HeaderLength) = L'\0';\r
630 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr); \r
631 }\r
8567300a
LG
632 \r
633 FreePool (AltConfigHdr);\r
84f9a9ec
LG
634 return EFI_SUCCESS; \r
635}\r
636\r
637/**\r
638 This function finds the matched DefaultName for the input DefaultId\r
639\r
640 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.\r
641 @param VarDefaultId Default Id\r
642 @param VarDefaultName Default Name string ID for the input default ID.\r
643 \r
644 @retval EFI_SUCCESS The mapped default name string ID is found.\r
645 @retval EFI_NOT_FOUND The mapped default name string ID is not found.\r
646**/\r
647EFI_STATUS\r
648FindDefaultName (\r
649 IN IFR_DEFAULT_DATA *DefaultIdArray, \r
650 IN UINT16 VarDefaultId, \r
651 OUT EFI_STRING_ID *VarDefaultName\r
652 )\r
653{\r
654 LIST_ENTRY *Link;\r
655 IFR_DEFAULT_DATA *DefaultData;\r
656\r
657 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
658 DefaultData = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
659 if (DefaultData->DefaultId == VarDefaultId) {\r
660 *VarDefaultName = DefaultData->DefaultName;\r
661 return EFI_SUCCESS;\r
662 }\r
663 }\r
664 \r
665 return EFI_NOT_FOUND;\r
666}\r
667\r
668/**\r
669 This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
670\r
671 @param BlockData The BlockData is updated to add new default value.\r
672 @param DefaultValueData The DefaultValue is added.\r
673\r
674**/\r
675VOID\r
676InsertDefaultValue (\r
677 IN IFR_BLOCK_DATA *BlockData,\r
678 IN IFR_DEFAULT_DATA *DefaultValueData\r
679 )\r
680{\r
681 LIST_ENTRY *Link;\r
682 IFR_DEFAULT_DATA *DefaultValueArray;\r
683\r
684 for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {\r
685 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
686 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
6e3f5b2a
LG
687 if (DefaultValueData->OpCode == EFI_IFR_DEFAULT_OP) {\r
688 //\r
689 // Update the default value array in BlockData.\r
690 //\r
691 DefaultValueArray->Value = DefaultValueData->Value;\r
692 } else if (DefaultValueArray->OpCode != EFI_IFR_DEFAULT_OP) {\r
693 //\r
694 // Update the default value array in BlockData.\r
695 //\r
696 DefaultValueArray->Value = DefaultValueData->Value;\r
697 }\r
84f9a9ec
LG
698 FreePool (DefaultValueData);\r
699 return;\r
700 } else if (DefaultValueArray->DefaultId > DefaultValueData->DefaultId) {\r
701 //\r
702 // Insert new default value data in the front of this default value array.\r
703 //\r
704 InsertTailList (Link, &DefaultValueData->Entry);\r
705 return;\r
706 }\r
707 }\r
708\r
709 //\r
710 // Insert new default value data in tail.\r
711 //\r
712 InsertTailList (Link, &DefaultValueData->Entry);\r
713 return;\r
714}\r
715\r
716/**\r
717 This function inserts new BlockData into the block link\r
718\r
719 @param BlockLink The list entry points to block array.\r
720 @param BlockData The point to BlockData is added.\r
721 \r
722**/\r
723VOID\r
724InsertBlockData (\r
725 IN LIST_ENTRY *BlockLink,\r
726 IN IFR_BLOCK_DATA **BlockData\r
727 )\r
728{\r
729 LIST_ENTRY *Link;\r
730 IFR_BLOCK_DATA *BlockArray;\r
731 IFR_BLOCK_DATA *BlockSingleData;\r
732\r
733 BlockSingleData = *BlockData;\r
734 \r
735 //\r
736 // Insert block data in its Offset and Width order.\r
737 //\r
738 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
739 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
740 if (BlockArray->Offset == BlockSingleData->Offset) {\r
741 if (BlockArray->Width > BlockSingleData->Width) {\r
742 //\r
743 // Insert this block data in the front of block array\r
744 //\r
745 InsertTailList (Link, &BlockSingleData->Entry);\r
746 return;\r
747 }\r
748\r
749 if (BlockArray->Width == BlockSingleData->Width) {\r
750 //\r
751 // The same block array has been added.\r
752 //\r
753 FreePool (BlockSingleData);\r
754 *BlockData = BlockArray;\r
755 return;\r
756 }\r
757 } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
758 //\r
759 // Insert new block data in the front of block array \r
760 //\r
761 InsertTailList (Link, &BlockSingleData->Entry);\r
762 return;\r
763 }\r
764 }\r
765 \r
766 //\r
767 // Add new block data into the tail.\r
768 //\r
769 InsertTailList (Link, &BlockSingleData->Entry);\r
770 return; \r
771}\r
772\r
773/**\r
774 This function checks VarOffset and VarWidth is in the block range.\r
775\r
776 @param BlockArray The block array is to be checked. \r
777 @param VarOffset Offset of var to the structure\r
778 @param VarWidth Width of var.\r
779 \r
780 @retval TRUE This Var is in the block range.\r
781 @retval FALSE This Var is not in the block range.\r
782**/\r
783BOOLEAN\r
784BlockArrayCheck (\r
785 IN IFR_BLOCK_DATA *RequestBlockArray,\r
786 IN UINT16 VarOffset,\r
787 IN UINT16 VarWidth\r
788 )\r
789{\r
790 LIST_ENTRY *Link;\r
791 IFR_BLOCK_DATA *BlockData;\r
792 \r
793 //\r
794 // No Request Block array, all vars are got.\r
795 //\r
796 if (RequestBlockArray == NULL) {\r
797 return TRUE;\r
798 }\r
799 \r
800 //\r
801 // Check the input var is in the request block range.\r
802 //\r
803 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
804 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
805 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
806 return TRUE;\r
807 }\r
808 }\r
809\r
810 return FALSE;\r
811}\r
812\r
813/**\r
814 This function parses Form Package to get the block array and the default\r
815 value array according to the request ConfigHdr.\r
816\r
817 @param Package Pointer to the form package data.\r
818 @param PackageLength Length of the pacakge.\r
819 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
820 the first found varstore will be as ConfigHdr.\r
821 @param RequestBlockArray The block array is retrieved from the request string.\r
822 @param VarStorageData VarStorage structure contains the got block and default value.\r
823 @param PIfrDefaultIdArray Point to the got default id and default name array.\r
824\r
825 @retval EFI_SUCCESS The block array and the default value array are got.\r
826 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
827 are conflicted. \r
828 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
829**/\r
830EFI_STATUS\r
831EFIAPI\r
832ParseIfrData (\r
833 IN UINT8 *Package,\r
834 IN UINT32 PackageLenth,\r
835 IN EFI_STRING ConfigHdr,\r
836 IN IFR_BLOCK_DATA *RequestBlockArray,\r
837 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
8567300a 838 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
84f9a9ec
LG
839 )\r
840{\r
841 EFI_STATUS Status;\r
842 UINTN IfrOffset;\r
843 EFI_IFR_VARSTORE *IfrVarStore;\r
844 EFI_IFR_OP_HEADER *IfrOpHdr;\r
845 EFI_IFR_ONE_OF *IfrOneOf;\r
846 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
847 EFI_IFR_DEFAULT *IfrDefault;\r
848 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
849 EFI_IFR_CHECKBOX *IfrCheckBox;\r
850 EFI_IFR_PASSWORD *IfrPassword;\r
851 EFI_IFR_STRING *IfrString;\r
84f9a9ec
LG
852 IFR_DEFAULT_DATA *DefaultData;\r
853 IFR_BLOCK_DATA *BlockData;\r
854 CHAR16 *VarStoreName;\r
855 UINT16 VarOffset;\r
856 UINT16 VarWidth;\r
857 EFI_STRING_ID VarDefaultName;\r
858 UINT16 VarDefaultId;\r
859 EFI_STRING GuidStr;\r
860 EFI_STRING NameStr;\r
861 EFI_STRING TempStr;\r
862 UINTN LengthString;\r
863\r
84f9a9ec
LG
864 LengthString = 0;\r
865 Status = EFI_SUCCESS;\r
866 GuidStr = NULL;\r
867 NameStr = NULL;\r
868 TempStr = NULL;\r
869 BlockData = NULL;\r
870 DefaultData = NULL;\r
84f9a9ec
LG
871\r
872 //\r
873 // Go through the form package to parse OpCode one by one.\r
874 //\r
875 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
876 while (IfrOffset < PackageLenth) {\r
877 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
878\r
879 switch (IfrOpHdr->OpCode) {\r
880 case EFI_IFR_VARSTORE_OP:\r
881 //\r
882 // VarStore is found. Don't need to search any more.\r
883 //\r
884 if (VarStorageData->Size != 0) {\r
885 break;\r
886 }\r
887\r
888 //\r
889 // Get the requied varstore information\r
890 // Add varstore by Guid and Name in ConfigHdr\r
891 // Make sure Offset is in varstore size and varstoreid\r
892 //\r
893 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
894 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
895 if (VarStoreName == NULL) {\r
896 Status = EFI_OUT_OF_RESOURCES;\r
897 goto Done;\r
898 }\r
899 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);\r
900\r
901 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);\r
902 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
903 LengthString = StrLen (GuidStr);\r
904 LengthString = LengthString + StrLen (NameStr) + 1;\r
905 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1f1cb2f2 906 if (TempStr == NULL) {\r
04da0b4a
LG
907 FreePool (GuidStr);\r
908 FreePool (NameStr);\r
1f1cb2f2 909 FreePool (VarStoreName);\r
84f9a9ec
LG
910 Status = EFI_OUT_OF_RESOURCES;\r
911 goto Done;\r
912 }\r
913 StrCpy (TempStr, GuidStr);\r
914 StrCat (TempStr, NameStr);\r
915 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
916 //\r
917 // Find the matched VarStore\r
918 //\r
919 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
920 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
921 VarStorageData->Size = IfrVarStore->Size;\r
922 VarStorageData->Name = VarStoreName;\r
923 } else {\r
924 //\r
925 // No found, free the allocated memory \r
926 //\r
927 FreePool (VarStoreName);\r
928 }\r
929 //\r
930 // Free alllocated temp string.\r
931 //\r
04da0b4a
LG
932 FreePool (GuidStr);\r
933 FreePool (NameStr);\r
84f9a9ec 934 FreePool (TempStr);\r
84f9a9ec
LG
935 break;\r
936\r
937 case EFI_IFR_DEFAULTSTORE_OP:\r
938 //\r
939 // Add new the map between default id and default name.\r
940 //\r
941 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
942 if (DefaultData == NULL) {\r
943 Status = EFI_OUT_OF_RESOURCES;\r
944 goto Done;\r
945 }\r
946 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
947 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
948 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);\r
949 DefaultData = NULL;\r
950 break;\r
951\r
952 case EFI_IFR_FORM_OP:\r
953 //\r
954 // No matched varstore is found and directly return.\r
955 //\r
956 if (VarStorageData->Size == 0) {\r
957 Status = EFI_SUCCESS;\r
958 goto Done;\r
959 }\r
960 break;\r
961\r
962 case EFI_IFR_ONE_OF_OP:\r
963 case EFI_IFR_NUMERIC_OP:\r
964 //\r
965 // Numeric and OneOf has the same opcode structure.\r
966 //\r
967\r
8567300a
LG
968 //\r
969 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
970 //\r
971 if (VarStorageData->Size == 0) {\r
972 Status = EFI_INVALID_PARAMETER;\r
973 goto Done;\r
974 }\r
84f9a9ec
LG
975 //\r
976 // Check whether this question is for the requested varstore.\r
977 //\r
978 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
979 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
980 break;\r
981 }\r
982 \r
983 //\r
984 // Get Offset/Width by Question header and OneOf Flags\r
985 //\r
986 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
987 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
988 //\r
989 // Check whether this question is in requested block array.\r
990 //\r
991 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
992 //\r
993 // This question is not in the requested string. Skip it.\r
994 //\r
995 break;\r
996 }\r
997\r
998 //\r
999 // Check this var question is in the var storage \r
1000 //\r
1001 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1002 Status = EFI_INVALID_PARAMETER;\r
1003 goto Done;\r
1004 }\r
1005 \r
1006 //\r
1007 // Set Block Data\r
1008 //\r
1009 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1010 if (BlockData == NULL) {\r
1011 Status = EFI_OUT_OF_RESOURCES;\r
1012 goto Done;\r
1013 }\r
1014 BlockData->Offset = VarOffset;\r
1015 BlockData->Width = VarWidth;\r
1016 BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
1017 BlockData->OpCode = IfrOpHdr->OpCode;\r
1018 BlockData->Scope = IfrOpHdr->Scope;\r
1019 InitializeListHead (&BlockData->DefaultValueEntry);\r
1020 //\r
1021 // Add Block Data into VarStorageData BlockEntry\r
1022 //\r
1023 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1024 break;\r
1025\r
1026 case EFI_IFR_ORDERED_LIST_OP:\r
1027 //\r
1028 // offset by question header\r
1029 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1030 // no default value and default id, how to define its default value?\r
1031 //\r
8567300a
LG
1032\r
1033 //\r
1034 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1035 //\r
1036 if (VarStorageData->Size == 0) {\r
1037 Status = EFI_INVALID_PARAMETER;\r
1038 goto Done;\r
1039 }\r
84f9a9ec
LG
1040 //\r
1041 // Check whether this question is for the requested varstore.\r
1042 //\r
1043 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1044 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1045 break;\r
1046 }\r
1047 \r
1048 //\r
1049 // Get Offset/Width by Question header and OneOf Flags\r
1050 //\r
1051 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
1052 VarWidth = IfrOrderedList->MaxContainers;\r
1053\r
1054 //\r
1055 // Check whether this question is in requested block array.\r
1056 //\r
1057 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1058 //\r
1059 // This question is not in the requested string. Skip it.\r
1060 //\r
1061 break;\r
1062 }\r
1063\r
1064 //\r
1065 // Check this var question is in the var storage \r
1066 //\r
1067 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1068 Status = EFI_INVALID_PARAMETER;\r
1069 goto Done;\r
1070 }\r
1071 \r
1072 //\r
1073 // Set Block Data\r
1074 //\r
1075 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1076 if (BlockData == NULL) {\r
1077 Status = EFI_OUT_OF_RESOURCES;\r
1078 goto Done;\r
1079 }\r
1080 BlockData->Offset = VarOffset;\r
1081 BlockData->Width = VarWidth;\r
1082 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
1083 BlockData->OpCode = IfrOpHdr->OpCode;\r
1084 BlockData->Scope = IfrOpHdr->Scope;\r
1085 InitializeListHead (&BlockData->DefaultValueEntry);\r
1086 \r
1087 //\r
1088 // Add Block Data into VarStorageData BlockEntry\r
1089 //\r
1090 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1091 break;\r
1092\r
1093 case EFI_IFR_CHECKBOX_OP:\r
1094 //\r
1095 // EFI_IFR_DEFAULT_OP\r
1096 // offset by question header\r
1097 // width is 1 sizeof (BOOLEAN)\r
1098 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1099 // value by DefaultOption\r
1100 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1101 // \r
1102\r
8567300a
LG
1103 //\r
1104 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1105 //\r
1106 if (VarStorageData->Size == 0) {\r
1107 Status = EFI_INVALID_PARAMETER;\r
1108 goto Done;\r
1109 }\r
84f9a9ec
LG
1110 //\r
1111 // Check whether this question is for the requested varstore.\r
1112 //\r
1113 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1114 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1115 break;\r
1116 }\r
1117 \r
1118 //\r
1119 // Get Offset/Width by Question header and OneOf Flags\r
1120 //\r
1121 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1122 VarWidth = sizeof (BOOLEAN);\r
1123\r
1124 //\r
1125 // Check whether this question is in requested block array.\r
1126 //\r
1127 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1128 //\r
1129 // This question is not in the requested string. Skip it.\r
1130 //\r
1131 break;\r
1132 }\r
1133\r
1134 //\r
1135 // Check this var question is in the var storage \r
1136 //\r
1137 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1138 Status = EFI_INVALID_PARAMETER;\r
1139 goto Done;\r
1140 }\r
1141 \r
1142 //\r
1143 // Set Block Data\r
1144 //\r
1145 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1146 if (BlockData == NULL) {\r
1147 Status = EFI_OUT_OF_RESOURCES;\r
1148 goto Done;\r
1149 }\r
1150 BlockData->Offset = VarOffset;\r
1151 BlockData->Width = VarWidth;\r
1152 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
1153 BlockData->OpCode = IfrOpHdr->OpCode;\r
1154 BlockData->Scope = IfrOpHdr->Scope;\r
1155 InitializeListHead (&BlockData->DefaultValueEntry);\r
1156 //\r
1157 // Add Block Data into VarStorageData BlockEntry\r
1158 //\r
1159 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1160 \r
1161 //\r
1162 // Add default value by CheckBox Flags \r
1163 //\r
1164 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1165 //\r
1166 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1167 //\r
1168 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1169 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1170 if (EFI_ERROR (Status)) {\r
1171 goto Done;\r
1172 }\r
1173 //\r
1174 // Prepare new DefaultValue\r
1175 //\r
1176 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1177 if (DefaultData == NULL) {\r
1178 Status = EFI_OUT_OF_RESOURCES;\r
1179 goto Done;\r
1180 }\r
6e3f5b2a 1181 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1182 DefaultData->DefaultId = VarDefaultId;\r
1183 DefaultData->DefaultName = VarDefaultName;\r
1184 DefaultData->Value = 1;\r
1185 //\r
1186 // Add DefaultValue into current BlockData\r
1187 //\r
1188 InsertDefaultValue (BlockData, DefaultData);\r
1189 }\r
1190\r
1191 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1192 //\r
1193 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1194 //\r
1195 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1196 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1197 if (EFI_ERROR (Status)) {\r
1198 goto Done;\r
1199 }\r
1200 //\r
1201 // Prepare new DefaultValue\r
1202 //\r
1203 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1204 if (DefaultData == NULL) {\r
1205 Status = EFI_OUT_OF_RESOURCES;\r
1206 goto Done;\r
1207 }\r
6e3f5b2a 1208 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1209 DefaultData->DefaultId = VarDefaultId;\r
1210 DefaultData->DefaultName = VarDefaultName;\r
1211 DefaultData->Value = 1;\r
1212 //\r
1213 // Add DefaultValue into current BlockData\r
1214 //\r
1215 InsertDefaultValue (BlockData, DefaultData);\r
1216 }\r
1217 break;\r
1218\r
1219 case EFI_IFR_STRING_OP:\r
1220 //\r
1221 // offset by question header\r
1222 // width MaxSize * sizeof (CHAR16)\r
1223 // no default value, only block array\r
1224 //\r
1225\r
8567300a
LG
1226 //\r
1227 // String question is not in IFR Form. This IFR form is not valid. \r
1228 //\r
1229 if (VarStorageData->Size == 0) {\r
1230 Status = EFI_INVALID_PARAMETER;\r
1231 goto Done;\r
1232 }\r
84f9a9ec
LG
1233 //\r
1234 // Check whether this question is for the requested varstore.\r
1235 //\r
1236 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1237 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1238 break;\r
1239 }\r
1240 \r
1241 //\r
1242 // Get Offset/Width by Question header and OneOf Flags\r
1243 //\r
1244 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
1245 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1246\r
1247 //\r
1248 // Check whether this question is in requested block array.\r
1249 //\r
1250 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1251 //\r
1252 // This question is not in the requested string. Skip it.\r
1253 //\r
1254 break;\r
1255 }\r
1256\r
1257 //\r
1258 // Check this var question is in the var storage \r
1259 //\r
1260 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1261 Status = EFI_INVALID_PARAMETER;\r
1262 goto Done;\r
1263 }\r
1264 \r
1265 //\r
1266 // Set Block Data\r
1267 //\r
1268 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1269 if (BlockData == NULL) {\r
1270 Status = EFI_OUT_OF_RESOURCES;\r
1271 goto Done;\r
1272 }\r
1273 BlockData->Offset = VarOffset;\r
1274 BlockData->Width = VarWidth;\r
1275 BlockData->QuestionId = IfrString->Question.QuestionId;\r
1276 BlockData->OpCode = IfrOpHdr->OpCode;\r
1277 InitializeListHead (&BlockData->DefaultValueEntry);\r
1278 \r
1279 //\r
1280 // Add Block Data into VarStorageData BlockEntry\r
1281 //\r
1282 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1283 \r
1284 //\r
1285 // No default value for string.\r
1286 //\r
1287 BlockData = NULL;\r
1288 break;\r
1289\r
1290 case EFI_IFR_PASSWORD_OP:\r
1291 //\r
1292 // offset by question header\r
1293 // width MaxSize * sizeof (CHAR16)\r
1294 // no default value, only block array\r
1295 //\r
1296\r
8567300a
LG
1297 //\r
1298 // Password question is not in IFR Form. This IFR form is not valid. \r
1299 //\r
1300 if (VarStorageData->Size == 0) {\r
1301 Status = EFI_INVALID_PARAMETER;\r
1302 goto Done;\r
1303 }\r
84f9a9ec
LG
1304 //\r
1305 // Check whether this question is for the requested varstore.\r
1306 //\r
1307 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1308 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1309 break;\r
1310 }\r
1311 \r
1312 //\r
1313 // Get Offset/Width by Question header and OneOf Flags\r
1314 //\r
1315 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
1316 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1317\r
1318 //\r
1319 // Check whether this question is in requested block array.\r
1320 //\r
1321 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1322 //\r
1323 // This question is not in the requested string. Skip it.\r
1324 //\r
1325 break;\r
1326 }\r
1327\r
1328 //\r
1329 // Check this var question is in the var storage \r
1330 //\r
1331 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1332 Status = EFI_INVALID_PARAMETER;\r
1333 goto Done;\r
1334 }\r
1335 \r
1336 //\r
1337 // Set Block Data\r
1338 //\r
1339 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1340 if (BlockData == NULL) {\r
1341 Status = EFI_OUT_OF_RESOURCES;\r
1342 goto Done;\r
1343 }\r
1344 BlockData->Offset = VarOffset;\r
1345 BlockData->Width = VarWidth;\r
1346 BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
1347 BlockData->OpCode = IfrOpHdr->OpCode;\r
1348 InitializeListHead (&BlockData->DefaultValueEntry);\r
1349 \r
1350 //\r
1351 // Add Block Data into VarStorageData BlockEntry\r
1352 //\r
1353 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1354 \r
1355 //\r
1356 // No default value for string.\r
1357 //\r
1358 BlockData = NULL;\r
1359 break;\r
1360\r
1361 case EFI_IFR_ONE_OF_OPTION_OP:\r
1362 //\r
1363 // No matched block data is ignored.\r
1364 //\r
1365 if (BlockData == NULL || BlockData->Scope == 0) {\r
1366 break;\r
1367 }\r
1368 \r
1369 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1370 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1371 //\r
1372 // Get ordered list option data type.\r
1373 //\r
1374 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1375 VarWidth = 1;\r
1376 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1377 VarWidth = 2;\r
1378 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1379 VarWidth = 4;\r
1380 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1381 VarWidth = 8;\r
1382 } else {\r
1383 //\r
1384 // Invalid ordered list option data type.\r
1385 //\r
1386 Status = EFI_INVALID_PARAMETER;\r
1387 goto Done;\r
1388 }\r
1389 //\r
1390 // Calculate Ordered list QuestionId width.\r
1391 //\r
1392 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
1393 BlockData = NULL;\r
1394 break;\r
1395 }\r
1396\r
1397 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1398 //\r
1399 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1400 //\r
1401 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1402 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1403 if (EFI_ERROR (Status)) {\r
1404 goto Done;\r
1405 }\r
1406 //\r
1407 // Prepare new DefaultValue\r
1408 //\r
1409 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1410 if (DefaultData == NULL) {\r
1411 Status = EFI_OUT_OF_RESOURCES;\r
1412 goto Done;\r
1413 }\r
6e3f5b2a 1414 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1415 DefaultData->DefaultId = VarDefaultId;\r
1416 DefaultData->DefaultName = VarDefaultName;\r
1417 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1418 //\r
1419 // Add DefaultValue into current BlockData\r
1420 //\r
1421 InsertDefaultValue (BlockData, DefaultData);\r
1422 }\r
1423\r
1424 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
1425 //\r
1426 // Set default ID to Manufacture ID and Get DefaultName String ID\r
1427 //\r
1428 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1429 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1430 if (EFI_ERROR (Status)) {\r
1431 goto Done;\r
1432 }\r
1433 //\r
1434 // Prepare new DefaultValue\r
1435 //\r
1436 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1437 if (DefaultData == NULL) {\r
1438 Status = EFI_OUT_OF_RESOURCES;\r
1439 goto Done;\r
1440 }\r
6e3f5b2a 1441 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1442 DefaultData->DefaultId = VarDefaultId;\r
1443 DefaultData->DefaultName = VarDefaultName;\r
1444 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1445 //\r
1446 // Add DefaultValue into current BlockData\r
1447 //\r
1448 InsertDefaultValue (BlockData, DefaultData);\r
1449 }\r
1450 break;\r
1451\r
1452 case EFI_IFR_DEFAULT_OP:\r
1453 //\r
1454 // Update Current BlockData to the default value.\r
1455 //\r
1456 if (BlockData == NULL || BlockData->Scope == 0) {\r
1457 //\r
1458 // No matched block data is ignored. \r
1459 //\r
1460 break;\r
1461 }\r
1462\r
1463 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1464 //\r
1465 // OrderedList Opcode is no default value.\r
1466 //\r
1467 break;\r
1468 }\r
1469 //\r
1470 // Get the DefaultId and DefaultName String ID\r
1471 //\r
1472 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
1473 VarDefaultId = IfrDefault->DefaultId;\r
1474 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1475 if (EFI_ERROR (Status)) {\r
1476 goto Done;\r
1477 }\r
1478 //\r
1479 // Prepare new DefaultValue\r
1480 //\r
1481 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1482 if (DefaultData == NULL) {\r
1483 Status = EFI_OUT_OF_RESOURCES;\r
1484 goto Done;\r
1485 }\r
6e3f5b2a 1486 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1487 DefaultData->DefaultId = VarDefaultId;\r
1488 DefaultData->DefaultName = VarDefaultName;\r
1489 DefaultData->Value = IfrDefault->Value.u64;\r
1490 //\r
1491 // Add DefaultValue into current BlockData\r
1492 //\r
1493 InsertDefaultValue (BlockData, DefaultData);\r
1494 break;\r
1495 case EFI_IFR_END_OP:\r
1496 //\r
8567300a 1497 // End Opcode is for Var question.\r
84f9a9ec
LG
1498 //\r
1499 if (BlockData != NULL && BlockData->Scope > 0) {\r
1500 BlockData->Scope--;\r
1501 }\r
1502 break;\r
1503 default:\r
1504 if (BlockData != NULL && BlockData->Scope > 0) {\r
1505 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
1506 }\r
1507 break;\r
1508 }\r
1509\r
1510 IfrOffset += IfrOpHdr->Length;\r
1511 }\r
1512\r
1513Done:\r
84f9a9ec
LG
1514 return Status; \r
1515}\r
1516\r
1517/**\r
1518 This function gets the full request string and full default value string by \r
1519 parsing IFR data in HII form packages. \r
1520 \r
1521 When Request points to NULL string, the request string and default value string \r
1522 for each varstore in form package will return. \r
1523\r
8567300a 1524 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
84f9a9ec
LG
1525 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
1526 @param Request Pointer to a null-terminated Unicode string in\r
1527 <ConfigRequest> format. When it doesn't contain\r
1528 any RequestElement, it will be updated to return \r
1529 the full RequestElement retrieved from IFR data.\r
1530 If it points to NULL, the request string for the first\r
1531 varstore in form package will be merged into a\r
1532 <MultiConfigRequest> format string and return. \r
1533 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
1534 <ConfigAltResp> format. When the pointer is to NULL,\r
1535 the full default value string retrieved from IFR data\r
1536 will return. When the pinter is to a string, the\r
1537 full default value string retrieved from IFR data\r
1538 will be merged into the input string and return.\r
1539 When Request points to NULL, the default value string \r
1540 for each varstore in form package will be merged into \r
1541 a <MultiConfigAltResp> format string and return.\r
ae79d2f9
LG
1542 @param PointerProgress Optional parameter, it can be be NULL. \r
1543 When it is not NULL, if Request is NULL, it returns NULL. \r
1544 On return, points to a character in the Request\r
1545 string. Points to the string's null terminator if\r
1546 request was successful. Points to the most recent\r
1547 & before the first failing name / value pair (or\r
1548 the beginning of the string if the failure is in\r
1549 the first name / value pair) if the request was\r
1550 not successful.\r
84f9a9ec
LG
1551 @retval EFI_SUCCESS The Results string is set to the full request string.\r
1552 And AltCfgResp contains all default value string.\r
1553 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
1554 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
1555 can't be found in Form package.\r
1556 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 1557 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
1558\r
1559**/\r
1560EFI_STATUS\r
1561EFIAPI\r
1562GetFullStringFromHiiFormPackages (\r
8567300a 1563 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
1564 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1565 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
1566 IN OUT EFI_STRING *AltCfgResp,\r
1567 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
1568 )\r
1569{\r
1570 EFI_STATUS Status;\r
8567300a
LG
1571 UINT8 *HiiFormPackage;\r
1572 UINTN PackageSize;\r
1573 UINTN ResultSize;\r
84f9a9ec
LG
1574 IFR_BLOCK_DATA *RequestBlockArray;\r
1575 IFR_BLOCK_DATA *BlockData;\r
1576 IFR_BLOCK_DATA *NextBlockData;\r
1577 IFR_DEFAULT_DATA *DefaultValueData;\r
1578 IFR_DEFAULT_DATA *DefaultId;\r
1579 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
1580 IFR_VARSTORAGE_DATA *VarStorageData;\r
1581 EFI_STRING DefaultAltCfgResp;\r
1582 EFI_STRING FullConfigRequest;\r
1583 EFI_STRING ConfigHdr;\r
1584 EFI_STRING GuidStr;\r
1585 EFI_STRING NameStr;\r
1586 EFI_STRING PathStr;\r
1587 EFI_STRING StringPtr;\r
ae79d2f9 1588 EFI_STRING Progress;\r
84f9a9ec
LG
1589 UINTN Length;\r
1590 UINT8 *TmpBuffer;\r
1591 UINT16 Offset;\r
1592 UINT16 Width;\r
1593 LIST_ENTRY *Link;\r
1594 LIST_ENTRY *LinkData;\r
1595 LIST_ENTRY *LinkDefault;\r
6e3f5b2a 1596 BOOLEAN DataExist;\r
84f9a9ec 1597\r
ae79d2f9
LG
1598 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
1599 return EFI_INVALID_PARAMETER;\r
1600 }\r
1601\r
84f9a9ec
LG
1602 //\r
1603 // Initialize the local variables.\r
1604 //\r
1605 RequestBlockArray = NULL;\r
8567300a 1606 DefaultIdArray = NULL;\r
84f9a9ec
LG
1607 VarStorageData = NULL;\r
1608 DefaultAltCfgResp = NULL;\r
1609 FullConfigRequest = NULL;\r
1610 ConfigHdr = NULL;\r
84f9a9ec
LG
1611 GuidStr = NULL;\r
1612 NameStr = NULL;\r
1613 PathStr = NULL;\r
8567300a
LG
1614 HiiFormPackage = NULL;\r
1615 ResultSize = 0;\r
1616 PackageSize = 0;\r
6e3f5b2a 1617 DataExist = FALSE;\r
ae79d2f9 1618 Progress = *Request;\r
6e3f5b2a 1619 \r
84f9a9ec 1620 //\r
8567300a
LG
1621 // 0. Get Hii Form Package by HiiHandle\r
1622 //\r
1623 Status = ExportFormPackages (\r
1624 &mPrivate, \r
1625 DataBaseRecord->Handle, \r
1626 DataBaseRecord->PackageList, \r
1627 0, \r
1628 PackageSize, \r
1629 HiiFormPackage,\r
1630 &ResultSize\r
1631 );\r
1632 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1633 return Status;\r
1634 }\r
8567300a
LG
1635 \r
1636 HiiFormPackage = AllocatePool (ResultSize);\r
1637 if (HiiFormPackage == NULL) {\r
1638 Status = EFI_OUT_OF_RESOURCES;\r
1639 goto Done;\r
84f9a9ec
LG
1640 }\r
1641\r
1642 //\r
8567300a 1643 // Get HiiFormPackage by HiiHandle\r
84f9a9ec 1644 //\r
8567300a
LG
1645 PackageSize = ResultSize;\r
1646 ResultSize = 0;\r
1647 Status = ExportFormPackages (\r
1648 &mPrivate, \r
1649 DataBaseRecord->Handle, \r
1650 DataBaseRecord->PackageList, \r
1651 0,\r
1652 PackageSize, \r
1653 HiiFormPackage,\r
1654 &ResultSize\r
1655 );\r
84f9a9ec
LG
1656 if (EFI_ERROR (Status)) {\r
1657 goto Done;\r
1658 }\r
1659\r
1660 //\r
8567300a 1661 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
1662 //\r
1663 StringPtr = NULL;\r
1664 if (*Request != NULL) {\r
ae79d2f9
LG
1665 StringPtr = *Request;\r
1666 //\r
1667 // Jump <ConfigHdr>\r
1668 //\r
1669 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1670 Status = EFI_INVALID_PARAMETER;\r
1671 goto Done;\r
1672 }\r
1673 StringPtr += StrLen (L"GUID=");\r
1674 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
1675 StringPtr++;\r
1676 }\r
1677 if (*StringPtr == L'\0') {\r
1678 Status = EFI_INVALID_PARAMETER;\r
1679 goto Done;\r
1680 }\r
1681 StringPtr += StrLen (L"&NAME=");\r
1682 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
1683 StringPtr++;\r
1684 }\r
1685 if (*StringPtr == L'\0') {\r
1686 Status = EFI_INVALID_PARAMETER;\r
1687 goto Done;\r
1688 }\r
1689 StringPtr += StrLen (L"&PATH=");\r
1690 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1691 StringPtr ++;\r
1692 }\r
1693 //\r
1694 // Check the following string &OFFSET=\r
1695 //\r
1696 if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
1697 Progress = StringPtr;\r
1698 Status = EFI_INVALID_PARAMETER;\r
1699 goto Done;\r
1700 } else if (*StringPtr == L'\0') {\r
1701 //\r
1702 // No request block is found.\r
1703 //\r
1704 StringPtr = NULL;\r
1705 }\r
84f9a9ec
LG
1706 }\r
1707 if (StringPtr != NULL) {\r
1708 //\r
1709 // Init RequestBlockArray\r
1710 //\r
1711 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1712 if (RequestBlockArray == NULL) {\r
1713 Status = EFI_OUT_OF_RESOURCES;\r
1714 goto Done;\r
1715 }\r
1716 InitializeListHead (&RequestBlockArray->Entry);\r
1717\r
1718 //\r
1719 // Get the request Block array from the request string\r
1720 // Offset and Width\r
1721 //\r
1722\r
1723 //\r
1724 // Parse each <RequestElement> if exists\r
1725 // Only <BlockName> format is supported by this help function.\r
1726 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
1727 //\r
1728 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
1729 //\r
1730 // Skip the OFFSET string\r
ae79d2f9
LG
1731 //\r
1732 Progress = StringPtr;\r
84f9a9ec
LG
1733 StringPtr += StrLen (L"&OFFSET=");\r
1734 //\r
1735 // Get Offset\r
1736 //\r
1737 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1738 if (EFI_ERROR (Status)) {\r
1739 goto Done;\r
1740 }\r
1741 Offset = 0;\r
1742 CopyMem (\r
1743 &Offset,\r
1744 TmpBuffer,\r
1745 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1746 );\r
1747 FreePool (TmpBuffer);\r
1748 \r
1749 StringPtr += Length;\r
1750 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1751 Status = EFI_INVALID_PARAMETER;\r
1752 goto Done;\r
1753 }\r
1754 StringPtr += StrLen (L"&WIDTH=");\r
1755 \r
1756 //\r
1757 // Get Width\r
1758 //\r
1759 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1760 if (EFI_ERROR (Status)) {\r
1761 goto Done;\r
1762 }\r
1763 Width = 0;\r
1764 CopyMem (\r
1765 &Width,\r
1766 TmpBuffer,\r
1767 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1768 );\r
1769 FreePool (TmpBuffer);\r
1770\r
1771 StringPtr += Length;\r
1772 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1773 Status = EFI_INVALID_PARAMETER;\r
1774 goto Done;\r
1775 }\r
1776 \r
1777 //\r
1778 // Set Block Data\r
1779 //\r
1780 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1781 if (BlockData == NULL) {\r
1782 Status = EFI_OUT_OF_RESOURCES;\r
1783 goto Done;\r
1784 }\r
1785 BlockData->Offset = Offset;\r
1786 BlockData->Width = Width;\r
1787 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
6e3f5b2a
LG
1788 \r
1789 //\r
1790 // Skip &VALUE string if &VALUE does exists.\r
1791 //\r
1792 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
1793 StringPtr += StrLen (L"&VALUE=");\r
84f9a9ec 1794\r
6e3f5b2a
LG
1795 //\r
1796 // Get Value\r
1797 //\r
1798 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1799 if (EFI_ERROR (Status)) {\r
1800 Status = EFI_INVALID_PARAMETER;\r
1801 goto Done;\r
1802 }\r
1803\r
1804 StringPtr += Length;\r
1805 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1806 Status = EFI_INVALID_PARAMETER;\r
1807 goto Done;\r
1808 }\r
1809 }\r
84f9a9ec
LG
1810 //\r
1811 // If '\0', parsing is finished. \r
1812 //\r
1813 if (*StringPtr == 0) {\r
1814 break;\r
1815 }\r
1816 }\r
1817 \r
1818 //\r
1819 // Merge the requested block data.\r
1820 //\r
1821 Link = RequestBlockArray->Entry.ForwardLink;\r
1822 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
1823 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1824 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
1825 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
1826 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1827 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
1828 }\r
1829 RemoveEntryList (Link->ForwardLink);\r
1830 FreePool (NextBlockData);\r
1831 continue;\r
1832 }\r
1833 Link = Link->ForwardLink; \r
1834 }\r
1835 }\r
1836 \r
1837 //\r
8567300a 1838 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 1839 //\r
84f9a9ec 1840\r
8567300a
LG
1841 //\r
1842 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
1843 //\r
1844 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1845 if (DefaultIdArray == NULL) {\r
1846 Status = EFI_OUT_OF_RESOURCES;\r
1847 goto Done;\r
1848 }\r
1849 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 1850\r
8567300a
LG
1851 //\r
1852 // Initialize VarStorageData to store the var store Block and Default value information.\r
1853 //\r
1854 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
1855 if (VarStorageData == NULL) {\r
1856 Status = EFI_OUT_OF_RESOURCES;\r
1857 goto Done;\r
1858 }\r
1859 InitializeListHead (&VarStorageData->Entry);\r
1860 InitializeListHead (&VarStorageData->BlockEntry);\r
84f9a9ec 1861\r
8567300a
LG
1862 //\r
1863 // Parse the opcode in form pacakge to get the default setting.\r
1864 //\r
1865 Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);\r
1866 if (EFI_ERROR (Status)) {\r
1867 goto Done;\r
84f9a9ec 1868 }\r
76c24251
LG
1869 \r
1870 //\r
1871 // No requested varstore in IFR data and directly return\r
1872 //\r
1873 if (VarStorageData->Size == 0) {\r
6e3f5b2a 1874 Status = EFI_SUCCESS;\r
76c24251
LG
1875 goto Done;\r
1876 }\r
84f9a9ec
LG
1877\r
1878 //\r
1879 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
1880 //\r
1881\r
1882 //\r
1883 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
1884 //\r
1885 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
1886 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
1887 GenerateSubStr (\r
1888 L"PATH=",\r
1889 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
1890 (VOID *) DevicePath,\r
1891 1,\r
1892 &PathStr\r
1893 );\r
1894 Length = StrLen (GuidStr);\r
1895 Length = Length + StrLen (NameStr);\r
1896 Length = Length + StrLen (PathStr) + 1;\r
1897 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1898 if (ConfigHdr == NULL) {\r
1899 Status = EFI_OUT_OF_RESOURCES;\r
1900 goto Done; \r
1901 }\r
1902 StrCpy (ConfigHdr, GuidStr);\r
1903 StrCat (ConfigHdr, NameStr);\r
1904 StrCat (ConfigHdr, PathStr);\r
1905\r
1906 //\r
1907 // Remove the last character L'&'\r
1908 //\r
1909 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
1910\r
1911 if (RequestBlockArray == NULL) {\r
1912 //\r
1913 // Append VarStorageData BlockEntry into *Request string\r
1914 // Now support only one varstore in a form package.\r
1915 //\r
1916\r
1917 //\r
1918 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
1919 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
1920 //\r
1921\r
1922 //\r
1923 // Compute the length of the entire request starting with <ConfigHdr> and a \r
1924 // Null-terminator\r
1925 //\r
ae79d2f9
LG
1926 DataExist = FALSE;\r
1927 Length = StrLen (ConfigHdr) + 1;\r
84f9a9ec
LG
1928\r
1929 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1930 //\r
1931 // Add <BlockName> length for each Offset/Width pair\r
1932 //\r
1933 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
1934 // | 8 | 4 | 7 | 4 |\r
1935 //\r
6e3f5b2a 1936 DataExist = TRUE;\r
84f9a9ec
LG
1937 Length = Length + (8 + 4 + 7 + 4);\r
1938 }\r
1939 \r
6e3f5b2a
LG
1940 //\r
1941 // No any request block data is found. The request string can't be constructed.\r
1942 //\r
1943 if (!DataExist) {\r
1944 Status = EFI_SUCCESS;\r
1945 goto Done;\r
1946 }\r
1947\r
84f9a9ec
LG
1948 //\r
1949 // Allocate buffer for the entire <ConfigRequest>\r
1950 //\r
1951 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
1952 if (FullConfigRequest == NULL) {\r
6e3f5b2a 1953 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
1954 goto Done;\r
1955 }\r
1956 StringPtr = FullConfigRequest;\r
1957 \r
1958 //\r
1959 // Start with <ConfigHdr>\r
1960 //\r
1961 StrCpy (StringPtr, ConfigHdr);\r
1962 StringPtr += StrLen (StringPtr);\r
1963\r
1964 //\r
1965 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
1966 //\r
1967 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1968 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1969 //\r
1970 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
1971 //\r
1972 UnicodeSPrint (\r
1973 StringPtr, \r
1974 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
1975 L"&OFFSET=%04X&WIDTH=%04X", \r
1976 BlockData->Offset, \r
1977 BlockData->Width\r
1978 );\r
1979 StringPtr += StrLen (StringPtr);\r
1980 }\r
1981 //\r
1982 // Set to the got full request string.\r
1983 //\r
1984 HiiToLower (FullConfigRequest);\r
1985 if (*Request != NULL) {\r
1986 FreePool (*Request);\r
1987 }\r
1988 *Request = FullConfigRequest;\r
1989 }\r
1990 \r
1991 //\r
1992 // 4. Construct Default Value string in AltResp according to request element.\r
1993 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
1994 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
1995 //\r
6e3f5b2a 1996 DataExist = FALSE;\r
93e3992d 1997 //\r
84f9a9ec 1998 // Add length for <ConfigHdr> + '\0'\r
93e3992d 1999 //\r
84f9a9ec
LG
2000 Length = StrLen (ConfigHdr) + 1;\r
2001 \r
2002 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2003 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2004 //\r
2005 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2006 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2007 //\r
2008 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2009 \r
2010 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2011 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2012 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2013 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2014 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2015 //\r
2016 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2017 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2018 //\r
6e3f5b2a
LG
2019 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2020 DataExist = TRUE;\r
84f9a9ec
LG
2021 }\r
2022 }\r
2023 }\r
93e3992d 2024 }\r
6e3f5b2a
LG
2025 \r
2026 //\r
2027 // No default value is found. The default string doesn't exist.\r
2028 //\r
2029 if (!DataExist) {\r
2030 Status = EFI_SUCCESS;\r
2031 goto Done;\r
2032 }\r
84f9a9ec 2033\r
93e3992d 2034 //\r
84f9a9ec 2035 // Allocate buffer for the entire <DefaultAltCfgResp>\r
93e3992d 2036 //\r
84f9a9ec
LG
2037 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2038 if (DefaultAltCfgResp == NULL) {\r
6e3f5b2a 2039 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2040 goto Done;\r
2041 }\r
2042 StringPtr = DefaultAltCfgResp;\r
93e3992d 2043\r
84f9a9ec
LG
2044 //\r
2045 // Start with <ConfigHdr>\r
2046 //\r
2047 StrCpy (StringPtr, ConfigHdr);\r
2048 StringPtr += StrLen (StringPtr);\r
93e3992d 2049\r
84f9a9ec
LG
2050 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2051 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2052 //\r
2053 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2054 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2055 //\r
2056 UnicodeSPrint (\r
2057 StringPtr, \r
2058 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2059 L"&%s&ALTCFG=%04X", \r
2060 ConfigHdr, \r
2061 DefaultId->DefaultName\r
2062 );\r
2063 StringPtr += StrLen (StringPtr);\r
2064 \r
2065 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2066 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2067 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2068 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2069 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2070 //\r
2071 // Add <BlockConfig>\r
2072 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2073 //\r
2074 UnicodeSPrint (\r
2075 StringPtr, \r
2076 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2077 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2078 BlockData->Offset, \r
2079 BlockData->Width\r
2080 );\r
2081 StringPtr += StrLen (StringPtr);\r
2082\r
2083 //\r
2084 // Convert Value to a hex string in "%x" format\r
2085 // NOTE: This is in the opposite byte that GUID and PATH use\r
2086 //\r
2087 Width = BlockData->Width;\r
2088 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2089 for (; Width > 0; Width--) {\r
2090 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2091 }\r
2092 }\r
2093 }\r
2094 }\r
93e3992d 2095 }\r
84f9a9ec 2096 HiiToLower (DefaultAltCfgResp);\r
93e3992d 2097\r
84f9a9ec
LG
2098 //\r
2099 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
2100 //\r
6e3f5b2a 2101 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
2102 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
2103 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
2104 } else if (*AltCfgResp == NULL) {\r
2105 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 2106 }\r
93e3992d 2107\r
84f9a9ec
LG
2108Done:\r
2109 if (RequestBlockArray != NULL) {\r
2110 //\r
2111 // Free Link Array RequestBlockArray\r
2112 //\r
2113 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2114 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2115 RemoveEntryList (&BlockData->Entry);\r
2116 FreePool (BlockData);\r
2117 }\r
2118\r
2119 FreePool (RequestBlockArray);\r
93e3992d 2120 }\r
63d55bb9 2121 \r
84f9a9ec
LG
2122 if (VarStorageData != NULL) {\r
2123 //\r
2124 // Free link array VarStorageData\r
2125 //\r
2126 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
2127 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2128 RemoveEntryList (&BlockData->Entry);\r
2129 //\r
2130 // Free default value link array\r
2131 //\r
2132 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
2133 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2134 RemoveEntryList (&DefaultValueData->Entry);\r
2135 FreePool (DefaultValueData);\r
2136 }\r
2137 FreePool (BlockData);\r
63d55bb9 2138 }\r
84f9a9ec 2139 FreePool (VarStorageData);\r
93e3992d 2140 }\r
2141\r
84f9a9ec
LG
2142 if (DefaultIdArray != NULL) {\r
2143 //\r
2144 // Free DefaultId Array\r
2145 //\r
2146 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
2147 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2148 RemoveEntryList (&DefaultId->Entry);\r
2149 FreePool (DefaultId);\r
2150 }\r
2151 FreePool (DefaultIdArray);\r
2152 }\r
2153 \r
2154 //\r
2155 // Free the allocated string \r
2156 //\r
2157 if (GuidStr != NULL) {\r
2158 FreePool (GuidStr);\r
2159 }\r
2160 if (NameStr != NULL) {\r
2161 FreePool (NameStr);\r
2162 }\r
2163 if (PathStr != NULL) {\r
2164 FreePool (PathStr);\r
2165 }\r
2166 if (ConfigHdr != NULL) {\r
2167 FreePool (ConfigHdr);\r
2168 }\r
93e3992d 2169\r
84f9a9ec
LG
2170 //\r
2171 // Free Pacakge data\r
2172 //\r
8567300a
LG
2173 if (HiiFormPackage != NULL) {\r
2174 FreePool (HiiFormPackage);\r
676df92c 2175 }\r
63d55bb9 2176\r
ae79d2f9
LG
2177 if (PointerProgress != NULL) {\r
2178 if (*Request == NULL) {\r
2179 *PointerProgress = NULL;\r
2180 } else if (EFI_ERROR (Status)) {\r
2181 *PointerProgress = Progress;\r
2182 } else {\r
2183 *PointerProgress = *Request + StrLen (*Request);\r
2184 }\r
2185 }\r
2186\r
93e3992d 2187 return Status;\r
2188}\r
2189\r
93e3992d 2190/**\r
2191 This function allows a caller to extract the current configuration\r
2192 for one or more named elements from one or more drivers.\r
2193\r
2194 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2195 instance.\r
2196 @param Request A null-terminated Unicode string in\r
2197 <MultiConfigRequest> format.\r
2198 @param Progress On return, points to a character in the Request\r
2199 string. Points to the string's null terminator if\r
2200 request was successful. Points to the most recent\r
2201 & before the first failing name / value pair (or\r
2202 the beginning of the string if the failure is in\r
2203 the first name / value pair) if the request was\r
2204 not successful.\r
2205 @param Results Null-terminated Unicode string in\r
2206 <MultiConfigAltResp> format which has all values\r
2207 filled in for the names in the Request string.\r
2208 String to be allocated by the called function.\r
2209\r
2210 @retval EFI_SUCCESS The Results string is filled with the values\r
2211 corresponding to all requested names.\r
2212 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2213 results that must be stored awaiting possible\r
2214 future protocols.\r
2215 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
2216 Progress set to the "G" in "GUID" of the routing\r
2217 header that doesn't match. Note: There is no\r
2218 requirement that all routing data be validated\r
2219 before any configuration extraction.\r
2220 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
2221 parameter would result in this type of error. The\r
2222 Progress parameter is set to NULL.\r
2223 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
2224 before the error or the beginning of the string.\r
2225 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
2226 name in question.\r
2227\r
2228**/\r
2229EFI_STATUS\r
2230EFIAPI\r
2231HiiConfigRoutingExtractConfig (\r
2232 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2233 IN CONST EFI_STRING Request,\r
2234 OUT EFI_STRING *Progress,\r
2235 OUT EFI_STRING *Results\r
2236 )\r
2237{\r
84f9a9ec 2238 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2239 EFI_STRING StringPtr;\r
2240 EFI_STRING ConfigRequest;\r
2241 UINTN Length;\r
2242 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2243 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 2244 EFI_STATUS Status;\r
84f9a9ec
LG
2245 LIST_ENTRY *Link;\r
2246 HII_DATABASE_RECORD *Database;\r
2247 UINT8 *DevicePathPkg;\r
2248 UINT8 *CurrentDevicePath;\r
93e3992d 2249 EFI_HANDLE DriverHandle;\r
84f9a9ec 2250 EFI_HII_HANDLE HiiHandle;\r
93e3992d 2251 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2252 EFI_STRING AccessProgress;\r
2253 EFI_STRING AccessResults;\r
84f9a9ec 2254 EFI_STRING DefaultResults;\r
8d00a0f1 2255 BOOLEAN FirstElement;\r
6e3f5b2a 2256 BOOLEAN IfrDataParsedFlag;\r
93e3992d 2257\r
2258 if (This == NULL || Progress == NULL || Results == NULL) {\r
2259 return EFI_INVALID_PARAMETER;\r
2260 }\r
2261\r
2262 if (Request == NULL) {\r
2263 *Progress = NULL;\r
2264 return EFI_INVALID_PARAMETER;\r
2265 }\r
2266\r
84f9a9ec 2267 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2268 StringPtr = Request;\r
2269 *Progress = StringPtr;\r
84f9a9ec
LG
2270 DefaultResults = NULL;\r
2271 ConfigRequest = NULL;\r
2272 Status = EFI_SUCCESS;\r
2273 AccessResults = NULL;\r
2274 DevicePath = NULL;\r
6e3f5b2a 2275 IfrDataParsedFlag = FALSE;\r
93e3992d 2276\r
2277 //\r
2278 // The first element of <MultiConfigRequest> should be\r
2279 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2280 //\r
2281 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2282 return EFI_INVALID_PARAMETER;\r
2283 }\r
2284\r
8d00a0f1 2285 FirstElement = TRUE;\r
2286\r
93e3992d 2287 //\r
2288 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2289 // Results if this fix length is insufficient.\r
2290 //\r
2291 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2292 if (*Results == NULL) {\r
2293 return EFI_OUT_OF_RESOURCES;\r
2294 }\r
2295\r
2296 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2297 //\r
2298 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
2299 // or most recent & before the error.\r
2300 //\r
2301 if (StringPtr == Request) {\r
2302 *Progress = StringPtr;\r
2303 } else {\r
2304 *Progress = StringPtr - 1;\r
2305 }\r
2306\r
2307 //\r
2308 // Process each <ConfigRequest> of <MultiConfigRequest>\r
2309 //\r
2310 Length = CalculateConfigStringLen (StringPtr);\r
2311 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2312 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
2313 Status = EFI_OUT_OF_RESOURCES;\r
2314 goto Done;\r
93e3992d 2315 }\r
2316 *(ConfigRequest + Length) = 0;\r
2317\r
2318 //\r
2319 // Get the UEFI device path\r
2320 //\r
2321 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
2322 if (EFI_ERROR (Status)) {\r
84f9a9ec 2323 goto Done;\r
93e3992d 2324 }\r
2325\r
2326 //\r
84f9a9ec
LG
2327 // Find driver which matches the routing data.\r
2328 //\r
2329 DriverHandle = NULL;\r
2330 HiiHandle = NULL;\r
8567300a 2331 Database = NULL;\r
84f9a9ec
LG
2332 for (Link = Private->DatabaseList.ForwardLink;\r
2333 Link != &Private->DatabaseList;\r
2334 Link = Link->ForwardLink\r
2335 ) {\r
2336 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
2337 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2338 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2339 if (CompareMem (\r
84f9a9ec
LG
2340 DevicePath,\r
2341 CurrentDevicePath,\r
6e3f5b2a
LG
2342 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2343 ) == 0) {\r
84f9a9ec
LG
2344 DriverHandle = Database->DriverHandle;\r
2345 HiiHandle = Database->Handle;\r
2346 break;\r
2347 }\r
2348 }\r
2349 }\r
2350 \r
2351 //\r
2352 // Try to find driver handle by device path.\r
93e3992d 2353 //\r
84f9a9ec
LG
2354 if (DriverHandle == NULL) {\r
2355 TempDevicePath = DevicePath;\r
2356 Status = gBS->LocateDevicePath (\r
2357 &gEfiDevicePathProtocolGuid,\r
2358 &TempDevicePath,\r
2359 &DriverHandle\r
2360 );\r
2361 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2362 //\r
2363 // Routing data does not match any known driver.\r
2364 // Set Progress to the 'G' in "GUID" of the routing header.\r
2365 //\r
2366 *Progress = StringPtr;\r
2367 Status = EFI_NOT_FOUND;\r
2368 goto Done;\r
2369 }\r
2370 }\r
2371 \r
2372 //\r
2373 // Check whether ConfigRequest contains request string OFFSET/WIDTH\r
2374 //\r
6e3f5b2a 2375 IfrDataParsedFlag = FALSE;\r
84f9a9ec 2376 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {\r
93e3992d 2377 //\r
84f9a9ec 2378 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 2379 //\r
6e3f5b2a 2380 IfrDataParsedFlag = TRUE;\r
ae79d2f9 2381 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 2382 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
2383 //\r
2384 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2385 // Map it to the progress on <MultiConfigRequest> then return it.\r
2386 //\r
2387 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
2388 goto Done;\r
2389 }\r
1f1cb2f2
LG
2390 //\r
2391 // Not any request block is found.\r
2392 //\r
2393 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {\r
76c24251 2394 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
2395 goto NextConfigString;\r
2396 }\r
93e3992d 2397 }\r
2398\r
2399 //\r
2400 // Call corresponding ConfigAccess protocol to extract settings\r
2401 //\r
2402 Status = gBS->HandleProtocol (\r
2403 DriverHandle,\r
2404 &gEfiHiiConfigAccessProtocolGuid,\r
2405 (VOID **) &ConfigAccess\r
2406 );\r
2407 ASSERT_EFI_ERROR (Status);\r
2408\r
2409 Status = ConfigAccess->ExtractConfig (\r
2410 ConfigAccess,\r
2411 ConfigRequest,\r
2412 &AccessProgress,\r
2413 &AccessResults\r
2414 );\r
2415 if (EFI_ERROR (Status)) {\r
2416 //\r
2417 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2418 // Map it to the progress on <MultiConfigRequest> then return it.\r
2419 //\r
8d00a0f1 2420 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 2421 goto Done;\r
93e3992d 2422 }\r
2423\r
2424 //\r
8d00a0f1 2425 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2426 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 2427 //\r
2428 ASSERT (*AccessProgress == 0);\r
8d00a0f1 2429\r
84f9a9ec
LG
2430 //\r
2431 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2432 //\r
ae79d2f9
LG
2433 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
2434 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
2435 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 2436 }\r
ae79d2f9 2437\r
84f9a9ec
LG
2438 FreePool (DevicePath);\r
2439 DevicePath = NULL;\r
84f9a9ec 2440\r
ae79d2f9
LG
2441 if (DefaultResults != NULL) {\r
2442 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2443 ASSERT_EFI_ERROR (Status);\r
2444 FreePool (DefaultResults);\r
2445 DefaultResults = NULL;\r
2446 }\r
2447 \r
76c24251 2448NextConfigString: \r
8d00a0f1 2449 if (!FirstElement) {\r
2450 Status = AppendToMultiString (Results, L"&");\r
2451 ASSERT_EFI_ERROR (Status);\r
2452 }\r
2453 \r
93e3992d 2454 Status = AppendToMultiString (Results, AccessResults);\r
2455 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 2456\r
2457 FirstElement = FALSE;\r
84f9a9ec 2458\r
676df92c 2459 FreePool (AccessResults);\r
93e3992d 2460 AccessResults = NULL;\r
676df92c 2461 FreePool (ConfigRequest);\r
93e3992d 2462 ConfigRequest = NULL;\r
2463\r
2464 //\r
2465 // Go to next <ConfigRequest> (skip '&').\r
2466 //\r
2467 StringPtr += Length;\r
2468 if (*StringPtr == 0) {\r
2469 *Progress = StringPtr;\r
2470 break;\r
2471 }\r
2472\r
2473 StringPtr++;\r
93e3992d 2474 }\r
2475\r
84f9a9ec
LG
2476Done:\r
2477 if (EFI_ERROR (Status)) {\r
2478 FreePool (*Results);\r
6e3f5b2a 2479 *Results = NULL;\r
84f9a9ec
LG
2480 }\r
2481 \r
2482 if (ConfigRequest != NULL) {\r
2483 FreePool (ConfigRequest);\r
2484 }\r
2485 \r
2486 if (AccessResults != NULL) {\r
2487 FreePool (AccessResults);\r
2488 }\r
2489 \r
2490 if (DefaultResults != NULL) {\r
2491 FreePool (DefaultResults);\r
2492 }\r
2493 \r
2494 if (DevicePath != NULL) {\r
2495 FreePool (DevicePath);\r
2496 } \r
93e3992d 2497\r
84f9a9ec 2498 return Status;\r
93e3992d 2499}\r
2500\r
2501\r
2502/**\r
2503 This function allows the caller to request the current configuration for the\r
2504 entirety of the current HII database and returns the data in a\r
2505 null-terminated Unicode string.\r
2506\r
2507 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2508 instance.\r
2509 @param Results Null-terminated Unicode string in\r
2510 <MultiConfigAltResp> format which has all values\r
2511 filled in for the names in the Request string.\r
2512 String to be allocated by the called function.\r
2513 De-allocation is up to the caller.\r
2514\r
2515 @retval EFI_SUCCESS The Results string is filled with the values\r
2516 corresponding to all requested names.\r
2517 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2518 results that must be stored awaiting possible\r
2519 future protocols.\r
2520 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
2521 parameter would result in this type of error.\r
2522\r
2523**/\r
2524EFI_STATUS\r
2525EFIAPI\r
2526HiiConfigRoutingExportConfig (\r
2527 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2528 OUT EFI_STRING *Results\r
2529 )\r
2530{\r
93e3992d 2531 EFI_STATUS Status;\r
93e3992d 2532 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
2533 EFI_STRING AccessResults;\r
2534 EFI_STRING Progress;\r
6e3f5b2a 2535 EFI_STRING StringPtr;\r
ae79d2f9 2536 EFI_STRING ConfigRequest;\r
8d00a0f1 2537 UINTN Index;\r
2538 EFI_HANDLE *ConfigAccessHandles;\r
2539 UINTN NumberConfigAccessHandles;\r
2540 BOOLEAN FirstElement;\r
84f9a9ec
LG
2541 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2542 EFI_HII_HANDLE HiiHandle;\r
2543 EFI_STRING DefaultResults;\r
2544 HII_DATABASE_PRIVATE_DATA *Private;\r
2545 LIST_ENTRY *Link;\r
2546 HII_DATABASE_RECORD *Database;\r
2547 UINT8 *DevicePathPkg;\r
2548 UINT8 *CurrentDevicePath;\r
ae79d2f9 2549 BOOLEAN IfrDataParsedFlag;\r
93e3992d 2550\r
2551 if (This == NULL || Results == NULL) {\r
2552 return EFI_INVALID_PARAMETER;\r
2553 }\r
2554\r
84f9a9ec
LG
2555 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2556\r
93e3992d 2557 //\r
2558 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2559 // Results if this fix length is insufficient.\r
2560 //\r
2561 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2562 if (*Results == NULL) {\r
2563 return EFI_OUT_OF_RESOURCES;\r
2564 }\r
2565\r
8d00a0f1 2566 NumberConfigAccessHandles = 0;\r
2567 Status = gBS->LocateHandleBuffer (\r
2568 ByProtocol,\r
2569 &gEfiHiiConfigAccessProtocolGuid,\r
2570 NULL,\r
2571 &NumberConfigAccessHandles,\r
2572 &ConfigAccessHandles\r
2573 );\r
2574 if (EFI_ERROR (Status)) {\r
2575 return Status;\r
2576 }\r
93e3992d 2577\r
8d00a0f1 2578 FirstElement = TRUE;\r
93e3992d 2579\r
8d00a0f1 2580 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 2581 Status = gBS->HandleProtocol (\r
8d00a0f1 2582 ConfigAccessHandles[Index],\r
93e3992d 2583 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 2584 (VOID **) &ConfigAccess\r
93e3992d 2585 );\r
8d00a0f1 2586 if (EFI_ERROR (Status)) {\r
2587 continue;\r
2588 }\r
93e3992d 2589\r
84f9a9ec
LG
2590 //\r
2591 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
2592 //\r
ae79d2f9 2593 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
2594 Progress = NULL;\r
2595 HiiHandle = NULL;\r
84f9a9ec 2596 DefaultResults = NULL;\r
8567300a 2597 Database = NULL;\r
ae79d2f9 2598 ConfigRequest = NULL;\r
84f9a9ec 2599 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
2600 if (DevicePath != NULL) {\r
2601 for (Link = Private->DatabaseList.ForwardLink;\r
2602 Link != &Private->DatabaseList;\r
2603 Link = Link->ForwardLink\r
2604 ) {\r
2605 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2606 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2607 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2608 if (CompareMem (\r
84f9a9ec
LG
2609 DevicePath,\r
2610 CurrentDevicePath,\r
6e3f5b2a
LG
2611 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2612 ) == 0) {\r
84f9a9ec
LG
2613 HiiHandle = Database->Handle;\r
2614 break;\r
2615 }\r
2616 }\r
2617 }\r
2618 }\r
2619\r
93e3992d 2620 Status = ConfigAccess->ExtractConfig (\r
2621 ConfigAccess,\r
6e3f5b2a 2622 NULL,\r
84f9a9ec 2623 &Progress,\r
93e3992d 2624 &AccessResults\r
2625 );\r
ae79d2f9 2626 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
2627 //\r
2628 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2629 //\r
2630 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
2631 IfrDataParsedFlag = TRUE;\r
2632 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
2633 //\r
2634 // Get the full request string to get the Current setting again.\r
2635 //\r
2636 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
2637 Status = ConfigAccess->ExtractConfig (\r
2638 ConfigAccess,\r
2639 ConfigRequest,\r
2640 &Progress,\r
2641 &AccessResults\r
2642 );\r
2643 FreePool (ConfigRequest);\r
2644 } else {\r
2645 Status = EFI_NOT_FOUND;\r
2646 }\r
2647 }\r
2648 }\r
2649\r
2650 if (!EFI_ERROR (Status)) {\r
2651 //\r
2652 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2653 //\r
2654 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
2655 StringPtr = StrStr (AccessResults, L"&GUID=");\r
2656 if (StringPtr != NULL) {\r
2657 *StringPtr = 0;\r
2658 }\r
2659 if (StrStr (AccessResults, L"&OFFSET=") != NULL) {\r
ae79d2f9
LG
2660 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
2661 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
2662 }\r
2663 if (StringPtr != NULL) {\r
2664 *StringPtr = L'&';\r
2665 }\r
2666 }\r
84f9a9ec
LG
2667 //\r
2668 // Merge the default sting from IFR code into the got setting from driver.\r
2669 //\r
2670 if (DefaultResults != NULL) {\r
8567300a
LG
2671 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2672 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 2673 FreePool (DefaultResults);\r
8567300a 2674 DefaultResults = NULL;\r
84f9a9ec
LG
2675 }\r
2676 \r
8d00a0f1 2677 //\r
2678 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2679 // which seperates the first <ConfigAltResp> and the following ones. \r
2680 //\r
2681 if (!FirstElement) {\r
2682 Status = AppendToMultiString (Results, L"&");\r
2683 ASSERT_EFI_ERROR (Status);\r
676df92c 2684 }\r
8d00a0f1 2685 \r
2686 Status = AppendToMultiString (Results, AccessResults);\r
2687 ASSERT_EFI_ERROR (Status);\r
93e3992d 2688\r
8d00a0f1 2689 FirstElement = FALSE;\r
2690 \r
2691 FreePool (AccessResults);\r
2692 AccessResults = NULL;\r
2693 }\r
93e3992d 2694 }\r
f4113e1f 2695 FreePool (ConfigAccessHandles);\r
93e3992d 2696\r
8d00a0f1 2697 return EFI_SUCCESS; \r
93e3992d 2698}\r
2699\r
2700\r
2701/**\r
2702 This function processes the results of processing forms and routes it to the\r
2703 appropriate handlers or storage.\r
2704\r
2705 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2706 instance.\r
2707 @param Configuration A null-terminated Unicode string in\r
2708 <MulltiConfigResp> format.\r
2709 @param Progress A pointer to a string filled in with the offset of\r
2710 the most recent & before the first failing name /\r
2711 value pair (or the beginning of the string if the\r
2712 failure is in the first name / value pair) or the\r
2713 terminating NULL if all was successful.\r
2714\r
2715 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
2716 distribution.\r
2717 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2718 results that must be stored awaiting possible\r
2719 future protocols.\r
2720 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
2721 would result in this type of error.\r
2722 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
2723 found.\r
2724\r
2725**/\r
2726EFI_STATUS\r
2727EFIAPI\r
813acf3a 2728HiiConfigRoutingRouteConfig (\r
93e3992d 2729 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2730 IN CONST EFI_STRING Configuration,\r
2731 OUT EFI_STRING *Progress\r
2732 )\r
2733{\r
84f9a9ec 2734 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2735 EFI_STRING StringPtr;\r
2736 EFI_STRING ConfigResp;\r
2737 UINTN Length;\r
2738 EFI_STATUS Status;\r
2739 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2740 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
2741 LIST_ENTRY *Link;\r
2742 HII_DATABASE_RECORD *Database;\r
2743 UINT8 *DevicePathPkg;\r
2744 UINT8 *CurrentDevicePath;\r
93e3992d 2745 EFI_HANDLE DriverHandle;\r
2746 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2747 EFI_STRING AccessProgress;\r
93e3992d 2748\r
2749 if (This == NULL || Progress == NULL) {\r
2750 return EFI_INVALID_PARAMETER;\r
2751 }\r
2752\r
2753 if (Configuration == NULL) {\r
2754 *Progress = NULL;\r
2755 return EFI_INVALID_PARAMETER;\r
2756 }\r
2757\r
84f9a9ec 2758 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2759 StringPtr = Configuration;\r
2760 *Progress = StringPtr;\r
2761\r
2762 //\r
2763 // The first element of <MultiConfigResp> should be\r
2764 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2765 //\r
2766 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2767 return EFI_INVALID_PARAMETER;\r
2768 }\r
2769\r
2770 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2771 //\r
2772 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
2773 // or most recent & before the error.\r
2774 //\r
2775 if (StringPtr == Configuration) {\r
2776 *Progress = StringPtr;\r
2777 } else {\r
2778 *Progress = StringPtr - 1;\r
2779 }\r
2780\r
2781 //\r
2782 // Process each <ConfigResp> of <MultiConfigResp>\r
2783 //\r
2784 Length = CalculateConfigStringLen (StringPtr);\r
2785 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2786 if (ConfigResp == NULL) {\r
2787 return EFI_OUT_OF_RESOURCES;\r
2788 }\r
2789 //\r
2790 // Append '\0' to the end of ConfigRequest\r
2791 //\r
2792 *(ConfigResp + Length) = 0;\r
2793\r
2794 //\r
2795 // Get the UEFI device path\r
2796 //\r
2797 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
2798 if (EFI_ERROR (Status)) {\r
676df92c 2799 FreePool (ConfigResp);\r
93e3992d 2800 return Status;\r
2801 }\r
2802\r
2803 //\r
84f9a9ec
LG
2804 // Find driver which matches the routing data.\r
2805 //\r
2806 DriverHandle = NULL;\r
84f9a9ec
LG
2807 for (Link = Private->DatabaseList.ForwardLink;\r
2808 Link != &Private->DatabaseList;\r
2809 Link = Link->ForwardLink\r
2810 ) {\r
2811 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2812\r
2813 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2814 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2815 if (CompareMem (\r
84f9a9ec
LG
2816 DevicePath,\r
2817 CurrentDevicePath,\r
6e3f5b2a
LG
2818 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2819 ) == 0) {\r
84f9a9ec
LG
2820 DriverHandle = Database->DriverHandle;\r
2821 break;\r
2822 }\r
2823 }\r
2824 }\r
93e3992d 2825\r
84f9a9ec
LG
2826 //\r
2827 // Try to find driver handle by device path.\r
2828 //\r
2829 if (DriverHandle == NULL) {\r
2830 TempDevicePath = DevicePath;\r
2831 Status = gBS->LocateDevicePath (\r
2832 &gEfiDevicePathProtocolGuid,\r
2833 &TempDevicePath,\r
2834 &DriverHandle\r
2835 );\r
2836 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2837 //\r
2838 // Routing data does not match any known driver.\r
2839 // Set Progress to the 'G' in "GUID" of the routing header.\r
2840 //\r
2841 FreePool (DevicePath);\r
2842 *Progress = StringPtr;\r
2843 FreePool (ConfigResp);\r
2844 return EFI_NOT_FOUND;\r
2845 }\r
93e3992d 2846 }\r
2847\r
84f9a9ec
LG
2848 FreePool (DevicePath);\r
2849\r
93e3992d 2850 //\r
2851 // Call corresponding ConfigAccess protocol to route settings\r
2852 //\r
2853 Status = gBS->HandleProtocol (\r
2854 DriverHandle,\r
2855 &gEfiHiiConfigAccessProtocolGuid,\r
2856 (VOID **) &ConfigAccess\r
2857 );\r
2858 ASSERT_EFI_ERROR (Status);\r
2859\r
2860 Status = ConfigAccess->RouteConfig (\r
2861 ConfigAccess,\r
2862 ConfigResp,\r
2863 &AccessProgress\r
2864 );\r
2865\r
2866 if (EFI_ERROR (Status)) {\r
2867 //\r
2868 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
2869 // Map it to the progress on <MultiConfigResp> then return it.\r
2870 //\r
8d00a0f1 2871 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 2872\r
676df92c 2873 FreePool (ConfigResp);\r
93e3992d 2874 return Status;\r
2875 }\r
2876\r
676df92c 2877 FreePool (ConfigResp);\r
93e3992d 2878 ConfigResp = NULL;\r
2879\r
2880 //\r
2881 // Go to next <ConfigResp> (skip '&').\r
2882 //\r
2883 StringPtr += Length;\r
2884 if (*StringPtr == 0) {\r
2885 *Progress = StringPtr;\r
2886 break;\r
2887 }\r
2888\r
2889 StringPtr++;\r
2890\r
2891 }\r
2892\r
2893 return EFI_SUCCESS;\r
93e3992d 2894}\r
2895\r
2896\r
2897/**\r
2898 This helper function is to be called by drivers to map configuration data\r
2899 stored in byte array ("block") formats such as UEFI Variables into current\r
2900 configuration strings.\r
2901\r
2902 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2903 instance.\r
2904 @param ConfigRequest A null-terminated Unicode string in\r
2905 <ConfigRequest> format.\r
2906 @param Block Array of bytes defining the block's configuration.\r
2907 @param BlockSize Length in bytes of Block.\r
2908 @param Config Filled-in configuration string. String allocated\r
2909 by the function. Returned only if call is\r
84f9a9ec 2910 successful. It is <ConfigResp> string format.\r
93e3992d 2911 @param Progress A pointer to a string filled in with the offset of\r
2912 the most recent & before the first failing\r
2913 name/value pair (or the beginning of the string if\r
2914 the failure is in the first name / value pair) or\r
2915 the terminating NULL if all was successful.\r
2916\r
2917 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
2918 terminator at the end of the ConfigRequest\r
2919 string.\r
2920 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
2921 points to the first character of ConfigRequest.\r
2922 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
2923 Block parameter would result in this type of\r
2924 error. Progress points to the first character of\r
2925 ConfigRequest.\r
2926 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
2927 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
2928 Block is left updated and Progress points at\r
2929 the "&" preceding the first non-<BlockName>.\r
2930\r
2931**/\r
2932EFI_STATUS\r
2933EFIAPI\r
2934HiiBlockToConfig (\r
2935 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2936 IN CONST EFI_STRING ConfigRequest,\r
2937 IN CONST UINT8 *Block,\r
2938 IN CONST UINTN BlockSize,\r
2939 OUT EFI_STRING *Config,\r
2940 OUT EFI_STRING *Progress\r
2941 )\r
2942{\r
84f9a9ec 2943 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2944 EFI_STRING StringPtr;\r
2945 UINTN Length;\r
2946 EFI_STATUS Status;\r
2947 EFI_STRING TmpPtr;\r
2948 UINT8 *TmpBuffer;\r
2949 UINTN Offset;\r
2950 UINTN Width;\r
2951 UINT8 *Value;\r
2952 EFI_STRING ValueStr;\r
2953 EFI_STRING ConfigElement;\r
63d55bb9
LG
2954 UINTN Index;\r
2955 UINT8 *TemBuffer;\r
2956 CHAR16 *TemString;\r
93e3992d 2957\r
2958 if (This == NULL || Progress == NULL || Config == NULL) {\r
2959 return EFI_INVALID_PARAMETER;\r
2960 }\r
2961\r
2962 if (Block == NULL || ConfigRequest == NULL) {\r
2963 *Progress = ConfigRequest;\r
2964 return EFI_INVALID_PARAMETER;\r
2965 }\r
2966\r
84f9a9ec
LG
2967\r
2968 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2969 ASSERT (Private != NULL);\r
2970\r
93e3992d 2971 StringPtr = ConfigRequest;\r
2972 ValueStr = NULL;\r
2973 Value = NULL;\r
2974 ConfigElement = NULL;\r
2975\r
2976 //\r
2977 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2978 // Results if this fix length is insufficient.\r
2979 //\r
2980 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2981 if (*Config == NULL) {\r
2982 return EFI_OUT_OF_RESOURCES;\r
2983 }\r
2984\r
2985 //\r
2986 // Jump <ConfigHdr>\r
2987 //\r
2988 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2989 *Progress = StringPtr;\r
2990 Status = EFI_INVALID_PARAMETER;\r
2991 goto Exit;\r
2992 }\r
2993 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
2994 StringPtr++;\r
2995 }\r
2996 if (*StringPtr == 0) {\r
76c24251 2997 *Progress = StringPtr - 1;\r
93e3992d 2998 Status = EFI_INVALID_PARAMETER;\r
2999 goto Exit;\r
3000 }\r
08e6463a 3001\r
3002 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3003 StringPtr++;\r
3004 }\r
3005 if (*StringPtr == 0) {\r
76c24251 3006 *Progress = StringPtr - 1;\r
08e6463a 3007 Status = EFI_INVALID_PARAMETER;\r
3008 goto Exit;\r
3009 }\r
3010 //\r
3011 // Skip '&'\r
3012 //\r
3013 StringPtr++;\r
93e3992d 3014\r
3015 //\r
3016 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
3017 //\r
3018 Length = StringPtr - ConfigRequest;\r
3019 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
3020\r
3021 //\r
3022 // Parse each <RequestElement> if exists\r
3023 // Only <BlockName> format is supported by this help function.\r
3024 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
3025 //\r
3026 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=&quo