]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
Fix the EBC build problem in DxeIpIoLib of r9374.
[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
e3d7cceb 871 VarDefaultName = 0;\r
84f9a9ec
LG
872\r
873 //\r
874 // Go through the form package to parse OpCode one by one.\r
875 //\r
876 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
877 while (IfrOffset < PackageLenth) {\r
878 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
879\r
880 switch (IfrOpHdr->OpCode) {\r
881 case EFI_IFR_VARSTORE_OP:\r
882 //\r
883 // VarStore is found. Don't need to search any more.\r
884 //\r
885 if (VarStorageData->Size != 0) {\r
886 break;\r
887 }\r
888\r
889 //\r
890 // Get the requied varstore information\r
891 // Add varstore by Guid and Name in ConfigHdr\r
892 // Make sure Offset is in varstore size and varstoreid\r
893 //\r
894 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
895 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
896 if (VarStoreName == NULL) {\r
897 Status = EFI_OUT_OF_RESOURCES;\r
898 goto Done;\r
899 }\r
900 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);\r
901\r
902 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);\r
903 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
904 LengthString = StrLen (GuidStr);\r
905 LengthString = LengthString + StrLen (NameStr) + 1;\r
906 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1f1cb2f2 907 if (TempStr == NULL) {\r
04da0b4a
LG
908 FreePool (GuidStr);\r
909 FreePool (NameStr);\r
1f1cb2f2 910 FreePool (VarStoreName);\r
84f9a9ec
LG
911 Status = EFI_OUT_OF_RESOURCES;\r
912 goto Done;\r
913 }\r
914 StrCpy (TempStr, GuidStr);\r
915 StrCat (TempStr, NameStr);\r
916 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
917 //\r
918 // Find the matched VarStore\r
919 //\r
920 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
921 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
922 VarStorageData->Size = IfrVarStore->Size;\r
923 VarStorageData->Name = VarStoreName;\r
924 } else {\r
925 //\r
926 // No found, free the allocated memory \r
927 //\r
928 FreePool (VarStoreName);\r
929 }\r
930 //\r
931 // Free alllocated temp string.\r
932 //\r
04da0b4a
LG
933 FreePool (GuidStr);\r
934 FreePool (NameStr);\r
84f9a9ec 935 FreePool (TempStr);\r
84f9a9ec
LG
936 break;\r
937\r
938 case EFI_IFR_DEFAULTSTORE_OP:\r
939 //\r
940 // Add new the map between default id and default name.\r
941 //\r
942 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
943 if (DefaultData == NULL) {\r
944 Status = EFI_OUT_OF_RESOURCES;\r
945 goto Done;\r
946 }\r
947 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
948 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
949 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);\r
950 DefaultData = NULL;\r
951 break;\r
952\r
953 case EFI_IFR_FORM_OP:\r
954 //\r
955 // No matched varstore is found and directly return.\r
956 //\r
957 if (VarStorageData->Size == 0) {\r
958 Status = EFI_SUCCESS;\r
959 goto Done;\r
960 }\r
961 break;\r
962\r
963 case EFI_IFR_ONE_OF_OP:\r
964 case EFI_IFR_NUMERIC_OP:\r
965 //\r
966 // Numeric and OneOf has the same opcode structure.\r
967 //\r
968\r
8567300a
LG
969 //\r
970 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
971 //\r
972 if (VarStorageData->Size == 0) {\r
973 Status = EFI_INVALID_PARAMETER;\r
974 goto Done;\r
975 }\r
84f9a9ec
LG
976 //\r
977 // Check whether this question is for the requested varstore.\r
978 //\r
979 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
980 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {\r
981 break;\r
982 }\r
983 \r
984 //\r
985 // Get Offset/Width by Question header and OneOf Flags\r
986 //\r
987 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
988 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
989 //\r
990 // Check whether this question is in requested block array.\r
991 //\r
992 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
993 //\r
994 // This question is not in the requested string. Skip it.\r
995 //\r
996 break;\r
997 }\r
998\r
999 //\r
1000 // Check this var question is in the var storage \r
1001 //\r
1002 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1003 Status = EFI_INVALID_PARAMETER;\r
1004 goto Done;\r
1005 }\r
1006 \r
1007 //\r
1008 // Set Block Data\r
1009 //\r
1010 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1011 if (BlockData == NULL) {\r
1012 Status = EFI_OUT_OF_RESOURCES;\r
1013 goto Done;\r
1014 }\r
1015 BlockData->Offset = VarOffset;\r
1016 BlockData->Width = VarWidth;\r
1017 BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
1018 BlockData->OpCode = IfrOpHdr->OpCode;\r
1019 BlockData->Scope = IfrOpHdr->Scope;\r
1020 InitializeListHead (&BlockData->DefaultValueEntry);\r
1021 //\r
1022 // Add Block Data into VarStorageData BlockEntry\r
1023 //\r
1024 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1025 break;\r
1026\r
1027 case EFI_IFR_ORDERED_LIST_OP:\r
1028 //\r
1029 // offset by question header\r
1030 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1031 // no default value and default id, how to define its default value?\r
1032 //\r
8567300a
LG
1033\r
1034 //\r
1035 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1036 //\r
1037 if (VarStorageData->Size == 0) {\r
1038 Status = EFI_INVALID_PARAMETER;\r
1039 goto Done;\r
1040 }\r
84f9a9ec
LG
1041 //\r
1042 // Check whether this question is for the requested varstore.\r
1043 //\r
1044 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1045 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1046 break;\r
1047 }\r
1048 \r
1049 //\r
1050 // Get Offset/Width by Question header and OneOf Flags\r
1051 //\r
1052 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
1053 VarWidth = IfrOrderedList->MaxContainers;\r
1054\r
1055 //\r
1056 // Check whether this question is in requested block array.\r
1057 //\r
1058 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1059 //\r
1060 // This question is not in the requested string. Skip it.\r
1061 //\r
1062 break;\r
1063 }\r
1064\r
1065 //\r
1066 // Check this var question is in the var storage \r
1067 //\r
1068 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1069 Status = EFI_INVALID_PARAMETER;\r
1070 goto Done;\r
1071 }\r
1072 \r
1073 //\r
1074 // Set Block Data\r
1075 //\r
1076 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1077 if (BlockData == NULL) {\r
1078 Status = EFI_OUT_OF_RESOURCES;\r
1079 goto Done;\r
1080 }\r
1081 BlockData->Offset = VarOffset;\r
1082 BlockData->Width = VarWidth;\r
1083 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
1084 BlockData->OpCode = IfrOpHdr->OpCode;\r
1085 BlockData->Scope = IfrOpHdr->Scope;\r
1086 InitializeListHead (&BlockData->DefaultValueEntry);\r
1087 \r
1088 //\r
1089 // Add Block Data into VarStorageData BlockEntry\r
1090 //\r
1091 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1092 break;\r
1093\r
1094 case EFI_IFR_CHECKBOX_OP:\r
1095 //\r
1096 // EFI_IFR_DEFAULT_OP\r
1097 // offset by question header\r
1098 // width is 1 sizeof (BOOLEAN)\r
1099 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1100 // value by DefaultOption\r
1101 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1102 // \r
1103\r
8567300a
LG
1104 //\r
1105 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1106 //\r
1107 if (VarStorageData->Size == 0) {\r
1108 Status = EFI_INVALID_PARAMETER;\r
1109 goto Done;\r
1110 }\r
84f9a9ec
LG
1111 //\r
1112 // Check whether this question is for the requested varstore.\r
1113 //\r
1114 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1115 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1116 break;\r
1117 }\r
1118 \r
1119 //\r
1120 // Get Offset/Width by Question header and OneOf Flags\r
1121 //\r
1122 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1123 VarWidth = sizeof (BOOLEAN);\r
1124\r
1125 //\r
1126 // Check whether this question is in requested block array.\r
1127 //\r
1128 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1129 //\r
1130 // This question is not in the requested string. Skip it.\r
1131 //\r
1132 break;\r
1133 }\r
1134\r
1135 //\r
1136 // Check this var question is in the var storage \r
1137 //\r
1138 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1139 Status = EFI_INVALID_PARAMETER;\r
1140 goto Done;\r
1141 }\r
1142 \r
1143 //\r
1144 // Set Block Data\r
1145 //\r
1146 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1147 if (BlockData == NULL) {\r
1148 Status = EFI_OUT_OF_RESOURCES;\r
1149 goto Done;\r
1150 }\r
1151 BlockData->Offset = VarOffset;\r
1152 BlockData->Width = VarWidth;\r
1153 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
1154 BlockData->OpCode = IfrOpHdr->OpCode;\r
1155 BlockData->Scope = IfrOpHdr->Scope;\r
1156 InitializeListHead (&BlockData->DefaultValueEntry);\r
1157 //\r
1158 // Add Block Data into VarStorageData BlockEntry\r
1159 //\r
1160 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1161 \r
1162 //\r
1163 // Add default value by CheckBox Flags \r
1164 //\r
1165 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1166 //\r
1167 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1168 //\r
1169 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1170 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1171 if (EFI_ERROR (Status)) {\r
1172 goto Done;\r
1173 }\r
1174 //\r
1175 // Prepare new DefaultValue\r
1176 //\r
1177 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1178 if (DefaultData == NULL) {\r
1179 Status = EFI_OUT_OF_RESOURCES;\r
1180 goto Done;\r
1181 }\r
6e3f5b2a 1182 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1183 DefaultData->DefaultId = VarDefaultId;\r
1184 DefaultData->DefaultName = VarDefaultName;\r
1185 DefaultData->Value = 1;\r
1186 //\r
1187 // Add DefaultValue into current BlockData\r
1188 //\r
1189 InsertDefaultValue (BlockData, DefaultData);\r
1190 }\r
1191\r
1192 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1193 //\r
1194 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1195 //\r
1196 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1197 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1198 if (EFI_ERROR (Status)) {\r
1199 goto Done;\r
1200 }\r
1201 //\r
1202 // Prepare new DefaultValue\r
1203 //\r
1204 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1205 if (DefaultData == NULL) {\r
1206 Status = EFI_OUT_OF_RESOURCES;\r
1207 goto Done;\r
1208 }\r
6e3f5b2a 1209 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1210 DefaultData->DefaultId = VarDefaultId;\r
1211 DefaultData->DefaultName = VarDefaultName;\r
1212 DefaultData->Value = 1;\r
1213 //\r
1214 // Add DefaultValue into current BlockData\r
1215 //\r
1216 InsertDefaultValue (BlockData, DefaultData);\r
1217 }\r
1218 break;\r
1219\r
1220 case EFI_IFR_STRING_OP:\r
1221 //\r
1222 // offset by question header\r
1223 // width MaxSize * sizeof (CHAR16)\r
1224 // no default value, only block array\r
1225 //\r
1226\r
8567300a
LG
1227 //\r
1228 // String question is not in IFR Form. This IFR form is not valid. \r
1229 //\r
1230 if (VarStorageData->Size == 0) {\r
1231 Status = EFI_INVALID_PARAMETER;\r
1232 goto Done;\r
1233 }\r
84f9a9ec
LG
1234 //\r
1235 // Check whether this question is for the requested varstore.\r
1236 //\r
1237 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1238 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1239 break;\r
1240 }\r
1241 \r
1242 //\r
1243 // Get Offset/Width by Question header and OneOf Flags\r
1244 //\r
1245 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
1246 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1247\r
1248 //\r
1249 // Check whether this question is in requested block array.\r
1250 //\r
1251 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1252 //\r
1253 // This question is not in the requested string. Skip it.\r
1254 //\r
1255 break;\r
1256 }\r
1257\r
1258 //\r
1259 // Check this var question is in the var storage \r
1260 //\r
1261 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1262 Status = EFI_INVALID_PARAMETER;\r
1263 goto Done;\r
1264 }\r
1265 \r
1266 //\r
1267 // Set Block Data\r
1268 //\r
1269 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1270 if (BlockData == NULL) {\r
1271 Status = EFI_OUT_OF_RESOURCES;\r
1272 goto Done;\r
1273 }\r
1274 BlockData->Offset = VarOffset;\r
1275 BlockData->Width = VarWidth;\r
1276 BlockData->QuestionId = IfrString->Question.QuestionId;\r
1277 BlockData->OpCode = IfrOpHdr->OpCode;\r
1278 InitializeListHead (&BlockData->DefaultValueEntry);\r
1279 \r
1280 //\r
1281 // Add Block Data into VarStorageData BlockEntry\r
1282 //\r
1283 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1284 \r
1285 //\r
1286 // No default value for string.\r
1287 //\r
1288 BlockData = NULL;\r
1289 break;\r
1290\r
1291 case EFI_IFR_PASSWORD_OP:\r
1292 //\r
1293 // offset by question header\r
1294 // width MaxSize * sizeof (CHAR16)\r
1295 // no default value, only block array\r
1296 //\r
1297\r
8567300a
LG
1298 //\r
1299 // Password question is not in IFR Form. This IFR form is not valid. \r
1300 //\r
1301 if (VarStorageData->Size == 0) {\r
1302 Status = EFI_INVALID_PARAMETER;\r
1303 goto Done;\r
1304 }\r
84f9a9ec
LG
1305 //\r
1306 // Check whether this question is for the requested varstore.\r
1307 //\r
1308 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
1309 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
1310 break;\r
1311 }\r
1312 \r
1313 //\r
1314 // Get Offset/Width by Question header and OneOf Flags\r
1315 //\r
1316 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
1317 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
1318\r
1319 //\r
1320 // Check whether this question is in requested block array.\r
1321 //\r
1322 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
1323 //\r
1324 // This question is not in the requested string. Skip it.\r
1325 //\r
1326 break;\r
1327 }\r
1328\r
1329 //\r
1330 // Check this var question is in the var storage \r
1331 //\r
1332 if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
1333 Status = EFI_INVALID_PARAMETER;\r
1334 goto Done;\r
1335 }\r
1336 \r
1337 //\r
1338 // Set Block Data\r
1339 //\r
1340 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1341 if (BlockData == NULL) {\r
1342 Status = EFI_OUT_OF_RESOURCES;\r
1343 goto Done;\r
1344 }\r
1345 BlockData->Offset = VarOffset;\r
1346 BlockData->Width = VarWidth;\r
1347 BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
1348 BlockData->OpCode = IfrOpHdr->OpCode;\r
1349 InitializeListHead (&BlockData->DefaultValueEntry);\r
1350 \r
1351 //\r
1352 // Add Block Data into VarStorageData BlockEntry\r
1353 //\r
1354 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1355 \r
1356 //\r
1357 // No default value for string.\r
1358 //\r
1359 BlockData = NULL;\r
1360 break;\r
1361\r
1362 case EFI_IFR_ONE_OF_OPTION_OP:\r
1363 //\r
1364 // No matched block data is ignored.\r
1365 //\r
1366 if (BlockData == NULL || BlockData->Scope == 0) {\r
1367 break;\r
1368 }\r
1369 \r
1370 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1371 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1372 //\r
1373 // Get ordered list option data type.\r
1374 //\r
1375 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
1376 VarWidth = 1;\r
1377 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1378 VarWidth = 2;\r
1379 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1380 VarWidth = 4;\r
1381 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1382 VarWidth = 8;\r
1383 } else {\r
1384 //\r
1385 // Invalid ordered list option data type.\r
1386 //\r
1387 Status = EFI_INVALID_PARAMETER;\r
1388 goto Done;\r
1389 }\r
1390 //\r
1391 // Calculate Ordered list QuestionId width.\r
1392 //\r
1393 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
1394 BlockData = NULL;\r
1395 break;\r
1396 }\r
1397\r
1398 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
1399 //\r
1400 // Set standard ID to Manufacture ID and Get DefaultName String ID\r
1401 //\r
1402 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1403 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1404 if (EFI_ERROR (Status)) {\r
1405 goto Done;\r
1406 }\r
1407 //\r
1408 // Prepare new DefaultValue\r
1409 //\r
1410 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1411 if (DefaultData == NULL) {\r
1412 Status = EFI_OUT_OF_RESOURCES;\r
1413 goto Done;\r
1414 }\r
6e3f5b2a 1415 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1416 DefaultData->DefaultId = VarDefaultId;\r
1417 DefaultData->DefaultName = VarDefaultName;\r
1418 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1419 //\r
1420 // Add DefaultValue into current BlockData\r
1421 //\r
1422 InsertDefaultValue (BlockData, DefaultData);\r
1423 }\r
1424\r
1425 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
1426 //\r
1427 // Set default ID to Manufacture ID and Get DefaultName String ID\r
1428 //\r
1429 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1430 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1431 if (EFI_ERROR (Status)) {\r
1432 goto Done;\r
1433 }\r
1434 //\r
1435 // Prepare new DefaultValue\r
1436 //\r
1437 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1438 if (DefaultData == NULL) {\r
1439 Status = EFI_OUT_OF_RESOURCES;\r
1440 goto Done;\r
1441 }\r
6e3f5b2a 1442 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1443 DefaultData->DefaultId = VarDefaultId;\r
1444 DefaultData->DefaultName = VarDefaultName;\r
1445 DefaultData->Value = IfrOneOfOption->Value.u64;\r
1446 //\r
1447 // Add DefaultValue into current BlockData\r
1448 //\r
1449 InsertDefaultValue (BlockData, DefaultData);\r
1450 }\r
1451 break;\r
1452\r
1453 case EFI_IFR_DEFAULT_OP:\r
1454 //\r
1455 // Update Current BlockData to the default value.\r
1456 //\r
1457 if (BlockData == NULL || BlockData->Scope == 0) {\r
1458 //\r
1459 // No matched block data is ignored. \r
1460 //\r
1461 break;\r
1462 }\r
1463\r
1464 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
1465 //\r
1466 // OrderedList Opcode is no default value.\r
1467 //\r
1468 break;\r
1469 }\r
1470 //\r
1471 // Get the DefaultId and DefaultName String ID\r
1472 //\r
1473 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
1474 VarDefaultId = IfrDefault->DefaultId;\r
1475 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
1476 if (EFI_ERROR (Status)) {\r
1477 goto Done;\r
1478 }\r
1479 //\r
1480 // Prepare new DefaultValue\r
1481 //\r
1482 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1483 if (DefaultData == NULL) {\r
1484 Status = EFI_OUT_OF_RESOURCES;\r
1485 goto Done;\r
1486 }\r
6e3f5b2a 1487 DefaultData->OpCode = IfrOpHdr->OpCode;\r
84f9a9ec
LG
1488 DefaultData->DefaultId = VarDefaultId;\r
1489 DefaultData->DefaultName = VarDefaultName;\r
1490 DefaultData->Value = IfrDefault->Value.u64;\r
1491 //\r
1492 // Add DefaultValue into current BlockData\r
1493 //\r
1494 InsertDefaultValue (BlockData, DefaultData);\r
1495 break;\r
1496 case EFI_IFR_END_OP:\r
1497 //\r
8567300a 1498 // End Opcode is for Var question.\r
84f9a9ec
LG
1499 //\r
1500 if (BlockData != NULL && BlockData->Scope > 0) {\r
1501 BlockData->Scope--;\r
1502 }\r
1503 break;\r
1504 default:\r
1505 if (BlockData != NULL && BlockData->Scope > 0) {\r
1506 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
1507 }\r
1508 break;\r
1509 }\r
1510\r
1511 IfrOffset += IfrOpHdr->Length;\r
1512 }\r
1513\r
1514Done:\r
84f9a9ec
LG
1515 return Status; \r
1516}\r
1517\r
1518/**\r
1519 This function gets the full request string and full default value string by \r
1520 parsing IFR data in HII form packages. \r
1521 \r
1522 When Request points to NULL string, the request string and default value string \r
1523 for each varstore in form package will return. \r
1524\r
8567300a 1525 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
84f9a9ec
LG
1526 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
1527 @param Request Pointer to a null-terminated Unicode string in\r
1528 <ConfigRequest> format. When it doesn't contain\r
1529 any RequestElement, it will be updated to return \r
1530 the full RequestElement retrieved from IFR data.\r
1531 If it points to NULL, the request string for the first\r
1532 varstore in form package will be merged into a\r
1533 <MultiConfigRequest> format string and return. \r
1534 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
1535 <ConfigAltResp> format. When the pointer is to NULL,\r
1536 the full default value string retrieved from IFR data\r
1537 will return. When the pinter is to a string, the\r
1538 full default value string retrieved from IFR data\r
1539 will be merged into the input string and return.\r
1540 When Request points to NULL, the default value string \r
1541 for each varstore in form package will be merged into \r
1542 a <MultiConfigAltResp> format string and return.\r
ae79d2f9
LG
1543 @param PointerProgress Optional parameter, it can be be NULL. \r
1544 When it is not NULL, if Request is NULL, it returns NULL. \r
1545 On return, points to a character in the Request\r
1546 string. Points to the string's null terminator if\r
1547 request was successful. Points to the most recent\r
1548 & before the first failing name / value pair (or\r
1549 the beginning of the string if the failure is in\r
1550 the first name / value pair) if the request was\r
1551 not successful.\r
84f9a9ec
LG
1552 @retval EFI_SUCCESS The Results string is set to the full request string.\r
1553 And AltCfgResp contains all default value string.\r
1554 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
1555 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
1556 can't be found in Form package.\r
1557 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 1558 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
1559\r
1560**/\r
1561EFI_STATUS\r
1562EFIAPI\r
1563GetFullStringFromHiiFormPackages (\r
8567300a 1564 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
1565 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1566 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
1567 IN OUT EFI_STRING *AltCfgResp,\r
1568 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
1569 )\r
1570{\r
1571 EFI_STATUS Status;\r
8567300a
LG
1572 UINT8 *HiiFormPackage;\r
1573 UINTN PackageSize;\r
1574 UINTN ResultSize;\r
84f9a9ec
LG
1575 IFR_BLOCK_DATA *RequestBlockArray;\r
1576 IFR_BLOCK_DATA *BlockData;\r
1577 IFR_BLOCK_DATA *NextBlockData;\r
1578 IFR_DEFAULT_DATA *DefaultValueData;\r
1579 IFR_DEFAULT_DATA *DefaultId;\r
1580 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
1581 IFR_VARSTORAGE_DATA *VarStorageData;\r
1582 EFI_STRING DefaultAltCfgResp;\r
1583 EFI_STRING FullConfigRequest;\r
1584 EFI_STRING ConfigHdr;\r
1585 EFI_STRING GuidStr;\r
1586 EFI_STRING NameStr;\r
1587 EFI_STRING PathStr;\r
1588 EFI_STRING StringPtr;\r
ae79d2f9 1589 EFI_STRING Progress;\r
84f9a9ec
LG
1590 UINTN Length;\r
1591 UINT8 *TmpBuffer;\r
1592 UINT16 Offset;\r
1593 UINT16 Width;\r
1594 LIST_ENTRY *Link;\r
1595 LIST_ENTRY *LinkData;\r
1596 LIST_ENTRY *LinkDefault;\r
6e3f5b2a 1597 BOOLEAN DataExist;\r
84f9a9ec 1598\r
ae79d2f9
LG
1599 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
1600 return EFI_INVALID_PARAMETER;\r
1601 }\r
1602\r
84f9a9ec
LG
1603 //\r
1604 // Initialize the local variables.\r
1605 //\r
1606 RequestBlockArray = NULL;\r
8567300a 1607 DefaultIdArray = NULL;\r
84f9a9ec
LG
1608 VarStorageData = NULL;\r
1609 DefaultAltCfgResp = NULL;\r
1610 FullConfigRequest = NULL;\r
1611 ConfigHdr = NULL;\r
84f9a9ec
LG
1612 GuidStr = NULL;\r
1613 NameStr = NULL;\r
1614 PathStr = NULL;\r
8567300a
LG
1615 HiiFormPackage = NULL;\r
1616 ResultSize = 0;\r
1617 PackageSize = 0;\r
6e3f5b2a 1618 DataExist = FALSE;\r
ae79d2f9 1619 Progress = *Request;\r
6e3f5b2a 1620 \r
84f9a9ec 1621 //\r
8567300a
LG
1622 // 0. Get Hii Form Package by HiiHandle\r
1623 //\r
1624 Status = ExportFormPackages (\r
1625 &mPrivate, \r
1626 DataBaseRecord->Handle, \r
1627 DataBaseRecord->PackageList, \r
1628 0, \r
1629 PackageSize, \r
1630 HiiFormPackage,\r
1631 &ResultSize\r
1632 );\r
1633 if (EFI_ERROR (Status)) {\r
84f9a9ec
LG
1634 return Status;\r
1635 }\r
8567300a
LG
1636 \r
1637 HiiFormPackage = AllocatePool (ResultSize);\r
1638 if (HiiFormPackage == NULL) {\r
1639 Status = EFI_OUT_OF_RESOURCES;\r
1640 goto Done;\r
84f9a9ec
LG
1641 }\r
1642\r
1643 //\r
8567300a 1644 // Get HiiFormPackage by HiiHandle\r
84f9a9ec 1645 //\r
8567300a
LG
1646 PackageSize = ResultSize;\r
1647 ResultSize = 0;\r
1648 Status = ExportFormPackages (\r
1649 &mPrivate, \r
1650 DataBaseRecord->Handle, \r
1651 DataBaseRecord->PackageList, \r
1652 0,\r
1653 PackageSize, \r
1654 HiiFormPackage,\r
1655 &ResultSize\r
1656 );\r
84f9a9ec
LG
1657 if (EFI_ERROR (Status)) {\r
1658 goto Done;\r
1659 }\r
1660\r
1661 //\r
8567300a 1662 // 1. Get the request block array by Request String when Request string containts the block array.\r
84f9a9ec
LG
1663 //\r
1664 StringPtr = NULL;\r
1665 if (*Request != NULL) {\r
ae79d2f9
LG
1666 StringPtr = *Request;\r
1667 //\r
1668 // Jump <ConfigHdr>\r
1669 //\r
1670 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1671 Status = EFI_INVALID_PARAMETER;\r
1672 goto Done;\r
1673 }\r
1674 StringPtr += StrLen (L"GUID=");\r
1675 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
1676 StringPtr++;\r
1677 }\r
1678 if (*StringPtr == L'\0') {\r
1679 Status = EFI_INVALID_PARAMETER;\r
1680 goto Done;\r
1681 }\r
1682 StringPtr += StrLen (L"&NAME=");\r
1683 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
1684 StringPtr++;\r
1685 }\r
1686 if (*StringPtr == L'\0') {\r
1687 Status = EFI_INVALID_PARAMETER;\r
1688 goto Done;\r
1689 }\r
1690 StringPtr += StrLen (L"&PATH=");\r
1691 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1692 StringPtr ++;\r
1693 }\r
1694 //\r
1695 // Check the following string &OFFSET=\r
1696 //\r
1697 if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
1698 Progress = StringPtr;\r
1699 Status = EFI_INVALID_PARAMETER;\r
1700 goto Done;\r
1701 } else if (*StringPtr == L'\0') {\r
1702 //\r
1703 // No request block is found.\r
1704 //\r
1705 StringPtr = NULL;\r
1706 }\r
84f9a9ec
LG
1707 }\r
1708 if (StringPtr != NULL) {\r
1709 //\r
1710 // Init RequestBlockArray\r
1711 //\r
1712 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1713 if (RequestBlockArray == NULL) {\r
1714 Status = EFI_OUT_OF_RESOURCES;\r
1715 goto Done;\r
1716 }\r
1717 InitializeListHead (&RequestBlockArray->Entry);\r
1718\r
1719 //\r
1720 // Get the request Block array from the request string\r
1721 // Offset and Width\r
1722 //\r
1723\r
1724 //\r
1725 // Parse each <RequestElement> if exists\r
1726 // Only <BlockName> format is supported by this help function.\r
1727 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
1728 //\r
1729 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
1730 //\r
1731 // Skip the OFFSET string\r
ae79d2f9
LG
1732 //\r
1733 Progress = StringPtr;\r
84f9a9ec
LG
1734 StringPtr += StrLen (L"&OFFSET=");\r
1735 //\r
1736 // Get Offset\r
1737 //\r
1738 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1739 if (EFI_ERROR (Status)) {\r
1740 goto Done;\r
1741 }\r
1742 Offset = 0;\r
1743 CopyMem (\r
1744 &Offset,\r
1745 TmpBuffer,\r
1746 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1747 );\r
1748 FreePool (TmpBuffer);\r
1749 \r
1750 StringPtr += Length;\r
1751 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1752 Status = EFI_INVALID_PARAMETER;\r
1753 goto Done;\r
1754 }\r
1755 StringPtr += StrLen (L"&WIDTH=");\r
1756 \r
1757 //\r
1758 // Get Width\r
1759 //\r
1760 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1761 if (EFI_ERROR (Status)) {\r
1762 goto Done;\r
1763 }\r
1764 Width = 0;\r
1765 CopyMem (\r
1766 &Width,\r
1767 TmpBuffer,\r
1768 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1769 );\r
1770 FreePool (TmpBuffer);\r
1771\r
1772 StringPtr += Length;\r
1773 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1774 Status = EFI_INVALID_PARAMETER;\r
1775 goto Done;\r
1776 }\r
1777 \r
1778 //\r
1779 // Set Block Data\r
1780 //\r
1781 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1782 if (BlockData == NULL) {\r
1783 Status = EFI_OUT_OF_RESOURCES;\r
1784 goto Done;\r
1785 }\r
1786 BlockData->Offset = Offset;\r
1787 BlockData->Width = Width;\r
1788 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
6e3f5b2a
LG
1789 \r
1790 //\r
1791 // Skip &VALUE string if &VALUE does exists.\r
1792 //\r
1793 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
1794 StringPtr += StrLen (L"&VALUE=");\r
84f9a9ec 1795\r
6e3f5b2a
LG
1796 //\r
1797 // Get Value\r
1798 //\r
1799 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1800 if (EFI_ERROR (Status)) {\r
1801 Status = EFI_INVALID_PARAMETER;\r
1802 goto Done;\r
1803 }\r
1804\r
1805 StringPtr += Length;\r
1806 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1807 Status = EFI_INVALID_PARAMETER;\r
1808 goto Done;\r
1809 }\r
1810 }\r
84f9a9ec
LG
1811 //\r
1812 // If '\0', parsing is finished. \r
1813 //\r
1814 if (*StringPtr == 0) {\r
1815 break;\r
1816 }\r
1817 }\r
1818 \r
1819 //\r
1820 // Merge the requested block data.\r
1821 //\r
1822 Link = RequestBlockArray->Entry.ForwardLink;\r
1823 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
1824 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1825 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
1826 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
1827 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1828 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
1829 }\r
1830 RemoveEntryList (Link->ForwardLink);\r
1831 FreePool (NextBlockData);\r
1832 continue;\r
1833 }\r
1834 Link = Link->ForwardLink; \r
1835 }\r
1836 }\r
1837 \r
1838 //\r
8567300a 1839 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 1840 //\r
84f9a9ec 1841\r
8567300a
LG
1842 //\r
1843 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
1844 //\r
1845 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1846 if (DefaultIdArray == NULL) {\r
1847 Status = EFI_OUT_OF_RESOURCES;\r
1848 goto Done;\r
1849 }\r
1850 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 1851\r
8567300a
LG
1852 //\r
1853 // Initialize VarStorageData to store the var store Block and Default value information.\r
1854 //\r
1855 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
1856 if (VarStorageData == NULL) {\r
1857 Status = EFI_OUT_OF_RESOURCES;\r
1858 goto Done;\r
1859 }\r
1860 InitializeListHead (&VarStorageData->Entry);\r
1861 InitializeListHead (&VarStorageData->BlockEntry);\r
84f9a9ec 1862\r
8567300a
LG
1863 //\r
1864 // Parse the opcode in form pacakge to get the default setting.\r
1865 //\r
1866 Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);\r
1867 if (EFI_ERROR (Status)) {\r
1868 goto Done;\r
84f9a9ec 1869 }\r
76c24251
LG
1870 \r
1871 //\r
1872 // No requested varstore in IFR data and directly return\r
1873 //\r
1874 if (VarStorageData->Size == 0) {\r
6e3f5b2a 1875 Status = EFI_SUCCESS;\r
76c24251
LG
1876 goto Done;\r
1877 }\r
84f9a9ec
LG
1878\r
1879 //\r
1880 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
1881 //\r
1882\r
1883 //\r
1884 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
1885 //\r
1886 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
1887 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
1888 GenerateSubStr (\r
1889 L"PATH=",\r
1890 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
1891 (VOID *) DevicePath,\r
1892 1,\r
1893 &PathStr\r
1894 );\r
1895 Length = StrLen (GuidStr);\r
1896 Length = Length + StrLen (NameStr);\r
1897 Length = Length + StrLen (PathStr) + 1;\r
1898 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1899 if (ConfigHdr == NULL) {\r
1900 Status = EFI_OUT_OF_RESOURCES;\r
1901 goto Done; \r
1902 }\r
1903 StrCpy (ConfigHdr, GuidStr);\r
1904 StrCat (ConfigHdr, NameStr);\r
1905 StrCat (ConfigHdr, PathStr);\r
1906\r
1907 //\r
1908 // Remove the last character L'&'\r
1909 //\r
1910 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
1911\r
1912 if (RequestBlockArray == NULL) {\r
1913 //\r
1914 // Append VarStorageData BlockEntry into *Request string\r
1915 // Now support only one varstore in a form package.\r
1916 //\r
1917\r
1918 //\r
1919 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
1920 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
1921 //\r
1922\r
1923 //\r
1924 // Compute the length of the entire request starting with <ConfigHdr> and a \r
1925 // Null-terminator\r
1926 //\r
ae79d2f9
LG
1927 DataExist = FALSE;\r
1928 Length = StrLen (ConfigHdr) + 1;\r
84f9a9ec
LG
1929\r
1930 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1931 //\r
1932 // Add <BlockName> length for each Offset/Width pair\r
1933 //\r
1934 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
1935 // | 8 | 4 | 7 | 4 |\r
1936 //\r
6e3f5b2a 1937 DataExist = TRUE;\r
84f9a9ec
LG
1938 Length = Length + (8 + 4 + 7 + 4);\r
1939 }\r
1940 \r
6e3f5b2a
LG
1941 //\r
1942 // No any request block data is found. The request string can't be constructed.\r
1943 //\r
1944 if (!DataExist) {\r
1945 Status = EFI_SUCCESS;\r
1946 goto Done;\r
1947 }\r
1948\r
84f9a9ec
LG
1949 //\r
1950 // Allocate buffer for the entire <ConfigRequest>\r
1951 //\r
1952 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
1953 if (FullConfigRequest == NULL) {\r
6e3f5b2a 1954 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
1955 goto Done;\r
1956 }\r
1957 StringPtr = FullConfigRequest;\r
1958 \r
1959 //\r
1960 // Start with <ConfigHdr>\r
1961 //\r
1962 StrCpy (StringPtr, ConfigHdr);\r
1963 StringPtr += StrLen (StringPtr);\r
1964\r
1965 //\r
1966 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
1967 //\r
1968 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
1969 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1970 //\r
1971 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
1972 //\r
1973 UnicodeSPrint (\r
1974 StringPtr, \r
1975 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
1976 L"&OFFSET=%04X&WIDTH=%04X", \r
1977 BlockData->Offset, \r
1978 BlockData->Width\r
1979 );\r
1980 StringPtr += StrLen (StringPtr);\r
1981 }\r
1982 //\r
1983 // Set to the got full request string.\r
1984 //\r
1985 HiiToLower (FullConfigRequest);\r
1986 if (*Request != NULL) {\r
1987 FreePool (*Request);\r
1988 }\r
1989 *Request = FullConfigRequest;\r
1990 }\r
1991 \r
1992 //\r
1993 // 4. Construct Default Value string in AltResp according to request element.\r
1994 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
1995 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
1996 //\r
6e3f5b2a 1997 DataExist = FALSE;\r
93e3992d 1998 //\r
84f9a9ec 1999 // Add length for <ConfigHdr> + '\0'\r
93e3992d 2000 //\r
84f9a9ec
LG
2001 Length = StrLen (ConfigHdr) + 1;\r
2002 \r
2003 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2004 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2005 //\r
2006 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2007 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2008 //\r
2009 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2010 \r
2011 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2012 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2013 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2014 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2015 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2016 //\r
2017 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2018 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2019 //\r
6e3f5b2a
LG
2020 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2021 DataExist = TRUE;\r
84f9a9ec
LG
2022 }\r
2023 }\r
2024 }\r
93e3992d 2025 }\r
6e3f5b2a
LG
2026 \r
2027 //\r
2028 // No default value is found. The default string doesn't exist.\r
2029 //\r
2030 if (!DataExist) {\r
2031 Status = EFI_SUCCESS;\r
2032 goto Done;\r
2033 }\r
84f9a9ec 2034\r
93e3992d 2035 //\r
84f9a9ec 2036 // Allocate buffer for the entire <DefaultAltCfgResp>\r
93e3992d 2037 //\r
84f9a9ec
LG
2038 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2039 if (DefaultAltCfgResp == NULL) {\r
6e3f5b2a 2040 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
2041 goto Done;\r
2042 }\r
2043 StringPtr = DefaultAltCfgResp;\r
93e3992d 2044\r
84f9a9ec
LG
2045 //\r
2046 // Start with <ConfigHdr>\r
2047 //\r
2048 StrCpy (StringPtr, ConfigHdr);\r
2049 StringPtr += StrLen (StringPtr);\r
93e3992d 2050\r
84f9a9ec
LG
2051 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2052 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2053 //\r
2054 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2055 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2056 //\r
2057 UnicodeSPrint (\r
2058 StringPtr, \r
2059 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2060 L"&%s&ALTCFG=%04X", \r
2061 ConfigHdr, \r
2062 DefaultId->DefaultName\r
2063 );\r
2064 StringPtr += StrLen (StringPtr);\r
2065 \r
2066 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2067 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2068 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2069 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2070 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
2071 //\r
2072 // Add <BlockConfig>\r
2073 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2074 //\r
2075 UnicodeSPrint (\r
2076 StringPtr, \r
2077 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2078 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2079 BlockData->Offset, \r
2080 BlockData->Width\r
2081 );\r
2082 StringPtr += StrLen (StringPtr);\r
2083\r
2084 //\r
2085 // Convert Value to a hex string in "%x" format\r
2086 // NOTE: This is in the opposite byte that GUID and PATH use\r
2087 //\r
2088 Width = BlockData->Width;\r
2089 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2090 for (; Width > 0; Width--) {\r
2091 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2092 }\r
2093 }\r
2094 }\r
2095 }\r
93e3992d 2096 }\r
84f9a9ec 2097 HiiToLower (DefaultAltCfgResp);\r
93e3992d 2098\r
84f9a9ec
LG
2099 //\r
2100 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
2101 //\r
6e3f5b2a 2102 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
2103 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
2104 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
2105 } else if (*AltCfgResp == NULL) {\r
2106 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 2107 }\r
93e3992d 2108\r
84f9a9ec
LG
2109Done:\r
2110 if (RequestBlockArray != NULL) {\r
2111 //\r
2112 // Free Link Array RequestBlockArray\r
2113 //\r
2114 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2115 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2116 RemoveEntryList (&BlockData->Entry);\r
2117 FreePool (BlockData);\r
2118 }\r
2119\r
2120 FreePool (RequestBlockArray);\r
93e3992d 2121 }\r
63d55bb9 2122 \r
84f9a9ec
LG
2123 if (VarStorageData != NULL) {\r
2124 //\r
2125 // Free link array VarStorageData\r
2126 //\r
2127 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
2128 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2129 RemoveEntryList (&BlockData->Entry);\r
2130 //\r
2131 // Free default value link array\r
2132 //\r
2133 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
2134 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2135 RemoveEntryList (&DefaultValueData->Entry);\r
2136 FreePool (DefaultValueData);\r
2137 }\r
2138 FreePool (BlockData);\r
63d55bb9 2139 }\r
84f9a9ec 2140 FreePool (VarStorageData);\r
93e3992d 2141 }\r
2142\r
84f9a9ec
LG
2143 if (DefaultIdArray != NULL) {\r
2144 //\r
2145 // Free DefaultId Array\r
2146 //\r
2147 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
2148 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
2149 RemoveEntryList (&DefaultId->Entry);\r
2150 FreePool (DefaultId);\r
2151 }\r
2152 FreePool (DefaultIdArray);\r
2153 }\r
2154 \r
2155 //\r
2156 // Free the allocated string \r
2157 //\r
2158 if (GuidStr != NULL) {\r
2159 FreePool (GuidStr);\r
2160 }\r
2161 if (NameStr != NULL) {\r
2162 FreePool (NameStr);\r
2163 }\r
2164 if (PathStr != NULL) {\r
2165 FreePool (PathStr);\r
2166 }\r
2167 if (ConfigHdr != NULL) {\r
2168 FreePool (ConfigHdr);\r
2169 }\r
93e3992d 2170\r
84f9a9ec
LG
2171 //\r
2172 // Free Pacakge data\r
2173 //\r
8567300a
LG
2174 if (HiiFormPackage != NULL) {\r
2175 FreePool (HiiFormPackage);\r
676df92c 2176 }\r
63d55bb9 2177\r
ae79d2f9
LG
2178 if (PointerProgress != NULL) {\r
2179 if (*Request == NULL) {\r
2180 *PointerProgress = NULL;\r
2181 } else if (EFI_ERROR (Status)) {\r
2182 *PointerProgress = Progress;\r
2183 } else {\r
2184 *PointerProgress = *Request + StrLen (*Request);\r
2185 }\r
2186 }\r
2187\r
93e3992d 2188 return Status;\r
2189}\r
2190\r
93e3992d 2191/**\r
2192 This function allows a caller to extract the current configuration\r
2193 for one or more named elements from one or more drivers.\r
2194\r
2195 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2196 instance.\r
2197 @param Request A null-terminated Unicode string in\r
2198 <MultiConfigRequest> format.\r
2199 @param Progress On return, points to a character in the Request\r
2200 string. Points to the string's null terminator if\r
2201 request was successful. Points to the most recent\r
2202 & before the first failing name / value pair (or\r
2203 the beginning of the string if the failure is in\r
2204 the first name / value pair) if the request was\r
2205 not successful.\r
2206 @param Results Null-terminated Unicode string in\r
2207 <MultiConfigAltResp> format which has all values\r
2208 filled in for the names in the Request string.\r
2209 String to be allocated by the called function.\r
2210\r
2211 @retval EFI_SUCCESS The Results string is filled with the values\r
2212 corresponding to all requested names.\r
2213 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2214 results that must be stored awaiting possible\r
2215 future protocols.\r
2216 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
2217 Progress set to the "G" in "GUID" of the routing\r
2218 header that doesn't match. Note: There is no\r
2219 requirement that all routing data be validated\r
2220 before any configuration extraction.\r
2221 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
2222 parameter would result in this type of error. The\r
2223 Progress parameter is set to NULL.\r
2224 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
2225 before the error or the beginning of the string.\r
2226 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
2227 name in question.\r
2228\r
2229**/\r
2230EFI_STATUS\r
2231EFIAPI\r
2232HiiConfigRoutingExtractConfig (\r
2233 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2234 IN CONST EFI_STRING Request,\r
2235 OUT EFI_STRING *Progress,\r
2236 OUT EFI_STRING *Results\r
2237 )\r
2238{\r
84f9a9ec 2239 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2240 EFI_STRING StringPtr;\r
2241 EFI_STRING ConfigRequest;\r
2242 UINTN Length;\r
2243 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2244 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 2245 EFI_STATUS Status;\r
84f9a9ec
LG
2246 LIST_ENTRY *Link;\r
2247 HII_DATABASE_RECORD *Database;\r
2248 UINT8 *DevicePathPkg;\r
2249 UINT8 *CurrentDevicePath;\r
93e3992d 2250 EFI_HANDLE DriverHandle;\r
84f9a9ec 2251 EFI_HII_HANDLE HiiHandle;\r
93e3992d 2252 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2253 EFI_STRING AccessProgress;\r
2254 EFI_STRING AccessResults;\r
84f9a9ec 2255 EFI_STRING DefaultResults;\r
8d00a0f1 2256 BOOLEAN FirstElement;\r
6e3f5b2a 2257 BOOLEAN IfrDataParsedFlag;\r
93e3992d 2258\r
2259 if (This == NULL || Progress == NULL || Results == NULL) {\r
2260 return EFI_INVALID_PARAMETER;\r
2261 }\r
2262\r
2263 if (Request == NULL) {\r
2264 *Progress = NULL;\r
2265 return EFI_INVALID_PARAMETER;\r
2266 }\r
2267\r
84f9a9ec 2268 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2269 StringPtr = Request;\r
2270 *Progress = StringPtr;\r
84f9a9ec
LG
2271 DefaultResults = NULL;\r
2272 ConfigRequest = NULL;\r
2273 Status = EFI_SUCCESS;\r
2274 AccessResults = NULL;\r
2275 DevicePath = NULL;\r
6e3f5b2a 2276 IfrDataParsedFlag = FALSE;\r
93e3992d 2277\r
2278 //\r
2279 // The first element of <MultiConfigRequest> should be\r
2280 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2281 //\r
2282 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2283 return EFI_INVALID_PARAMETER;\r
2284 }\r
2285\r
8d00a0f1 2286 FirstElement = TRUE;\r
2287\r
93e3992d 2288 //\r
2289 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2290 // Results if this fix length is insufficient.\r
2291 //\r
2292 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2293 if (*Results == NULL) {\r
2294 return EFI_OUT_OF_RESOURCES;\r
2295 }\r
2296\r
2297 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2298 //\r
2299 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
2300 // or most recent & before the error.\r
2301 //\r
2302 if (StringPtr == Request) {\r
2303 *Progress = StringPtr;\r
2304 } else {\r
2305 *Progress = StringPtr - 1;\r
2306 }\r
2307\r
2308 //\r
2309 // Process each <ConfigRequest> of <MultiConfigRequest>\r
2310 //\r
2311 Length = CalculateConfigStringLen (StringPtr);\r
2312 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2313 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
2314 Status = EFI_OUT_OF_RESOURCES;\r
2315 goto Done;\r
93e3992d 2316 }\r
2317 *(ConfigRequest + Length) = 0;\r
2318\r
2319 //\r
2320 // Get the UEFI device path\r
2321 //\r
2322 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
2323 if (EFI_ERROR (Status)) {\r
84f9a9ec 2324 goto Done;\r
93e3992d 2325 }\r
2326\r
2327 //\r
84f9a9ec
LG
2328 // Find driver which matches the routing data.\r
2329 //\r
2330 DriverHandle = NULL;\r
2331 HiiHandle = NULL;\r
8567300a 2332 Database = NULL;\r
84f9a9ec
LG
2333 for (Link = Private->DatabaseList.ForwardLink;\r
2334 Link != &Private->DatabaseList;\r
2335 Link = Link->ForwardLink\r
2336 ) {\r
2337 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
2338 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2339 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2340 if (CompareMem (\r
84f9a9ec
LG
2341 DevicePath,\r
2342 CurrentDevicePath,\r
6e3f5b2a
LG
2343 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2344 ) == 0) {\r
84f9a9ec
LG
2345 DriverHandle = Database->DriverHandle;\r
2346 HiiHandle = Database->Handle;\r
2347 break;\r
2348 }\r
2349 }\r
2350 }\r
2351 \r
2352 //\r
2353 // Try to find driver handle by device path.\r
93e3992d 2354 //\r
84f9a9ec
LG
2355 if (DriverHandle == NULL) {\r
2356 TempDevicePath = DevicePath;\r
2357 Status = gBS->LocateDevicePath (\r
2358 &gEfiDevicePathProtocolGuid,\r
2359 &TempDevicePath,\r
2360 &DriverHandle\r
2361 );\r
2362 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2363 //\r
2364 // Routing data does not match any known driver.\r
2365 // Set Progress to the 'G' in "GUID" of the routing header.\r
2366 //\r
2367 *Progress = StringPtr;\r
2368 Status = EFI_NOT_FOUND;\r
2369 goto Done;\r
2370 }\r
2371 }\r
2372 \r
2373 //\r
2374 // Check whether ConfigRequest contains request string OFFSET/WIDTH\r
2375 //\r
6e3f5b2a 2376 IfrDataParsedFlag = FALSE;\r
84f9a9ec 2377 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {\r
93e3992d 2378 //\r
84f9a9ec 2379 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 2380 //\r
6e3f5b2a 2381 IfrDataParsedFlag = TRUE;\r
ae79d2f9 2382 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 2383 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
2384 //\r
2385 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2386 // Map it to the progress on <MultiConfigRequest> then return it.\r
2387 //\r
2388 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
2389 goto Done;\r
2390 }\r
1f1cb2f2
LG
2391 //\r
2392 // Not any request block is found.\r
2393 //\r
2394 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {\r
76c24251 2395 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
2396 goto NextConfigString;\r
2397 }\r
93e3992d 2398 }\r
2399\r
2400 //\r
2401 // Call corresponding ConfigAccess protocol to extract settings\r
2402 //\r
2403 Status = gBS->HandleProtocol (\r
2404 DriverHandle,\r
2405 &gEfiHiiConfigAccessProtocolGuid,\r
2406 (VOID **) &ConfigAccess\r
2407 );\r
2408 ASSERT_EFI_ERROR (Status);\r
2409\r
2410 Status = ConfigAccess->ExtractConfig (\r
2411 ConfigAccess,\r
2412 ConfigRequest,\r
2413 &AccessProgress,\r
2414 &AccessResults\r
2415 );\r
2416 if (EFI_ERROR (Status)) {\r
2417 //\r
2418 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
2419 // Map it to the progress on <MultiConfigRequest> then return it.\r
2420 //\r
8d00a0f1 2421 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 2422 goto Done;\r
93e3992d 2423 }\r
2424\r
2425 //\r
8d00a0f1 2426 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2427 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 2428 //\r
2429 ASSERT (*AccessProgress == 0);\r
8d00a0f1 2430\r
84f9a9ec
LG
2431 //\r
2432 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2433 //\r
ae79d2f9
LG
2434 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
2435 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
2436 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 2437 }\r
ae79d2f9 2438\r
84f9a9ec
LG
2439 FreePool (DevicePath);\r
2440 DevicePath = NULL;\r
84f9a9ec 2441\r
ae79d2f9
LG
2442 if (DefaultResults != NULL) {\r
2443 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2444 ASSERT_EFI_ERROR (Status);\r
2445 FreePool (DefaultResults);\r
2446 DefaultResults = NULL;\r
2447 }\r
2448 \r
76c24251 2449NextConfigString: \r
8d00a0f1 2450 if (!FirstElement) {\r
2451 Status = AppendToMultiString (Results, L"&");\r
2452 ASSERT_EFI_ERROR (Status);\r
2453 }\r
2454 \r
93e3992d 2455 Status = AppendToMultiString (Results, AccessResults);\r
2456 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 2457\r
2458 FirstElement = FALSE;\r
84f9a9ec 2459\r
676df92c 2460 FreePool (AccessResults);\r
93e3992d 2461 AccessResults = NULL;\r
676df92c 2462 FreePool (ConfigRequest);\r
93e3992d 2463 ConfigRequest = NULL;\r
2464\r
2465 //\r
2466 // Go to next <ConfigRequest> (skip '&').\r
2467 //\r
2468 StringPtr += Length;\r
2469 if (*StringPtr == 0) {\r
2470 *Progress = StringPtr;\r
2471 break;\r
2472 }\r
2473\r
2474 StringPtr++;\r
93e3992d 2475 }\r
2476\r
84f9a9ec
LG
2477Done:\r
2478 if (EFI_ERROR (Status)) {\r
2479 FreePool (*Results);\r
6e3f5b2a 2480 *Results = NULL;\r
84f9a9ec
LG
2481 }\r
2482 \r
2483 if (ConfigRequest != NULL) {\r
2484 FreePool (ConfigRequest);\r
2485 }\r
2486 \r
2487 if (AccessResults != NULL) {\r
2488 FreePool (AccessResults);\r
2489 }\r
2490 \r
2491 if (DefaultResults != NULL) {\r
2492 FreePool (DefaultResults);\r
2493 }\r
2494 \r
2495 if (DevicePath != NULL) {\r
2496 FreePool (DevicePath);\r
2497 } \r
93e3992d 2498\r
84f9a9ec 2499 return Status;\r
93e3992d 2500}\r
2501\r
2502\r
2503/**\r
2504 This function allows the caller to request the current configuration for the\r
2505 entirety of the current HII database and returns the data in a\r
2506 null-terminated Unicode string.\r
2507\r
2508 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2509 instance.\r
2510 @param Results Null-terminated Unicode string in\r
2511 <MultiConfigAltResp> format which has all values\r
2512 filled in for the names in the Request string.\r
2513 String to be allocated by the called function.\r
2514 De-allocation is up to the caller.\r
2515\r
2516 @retval EFI_SUCCESS The Results string is filled with the values\r
2517 corresponding to all requested names.\r
2518 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2519 results that must be stored awaiting possible\r
2520 future protocols.\r
2521 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
2522 parameter would result in this type of error.\r
2523\r
2524**/\r
2525EFI_STATUS\r
2526EFIAPI\r
2527HiiConfigRoutingExportConfig (\r
2528 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2529 OUT EFI_STRING *Results\r
2530 )\r
2531{\r
93e3992d 2532 EFI_STATUS Status;\r
93e3992d 2533 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
2534 EFI_STRING AccessResults;\r
2535 EFI_STRING Progress;\r
6e3f5b2a 2536 EFI_STRING StringPtr;\r
ae79d2f9 2537 EFI_STRING ConfigRequest;\r
8d00a0f1 2538 UINTN Index;\r
2539 EFI_HANDLE *ConfigAccessHandles;\r
2540 UINTN NumberConfigAccessHandles;\r
2541 BOOLEAN FirstElement;\r
84f9a9ec
LG
2542 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2543 EFI_HII_HANDLE HiiHandle;\r
2544 EFI_STRING DefaultResults;\r
2545 HII_DATABASE_PRIVATE_DATA *Private;\r
2546 LIST_ENTRY *Link;\r
2547 HII_DATABASE_RECORD *Database;\r
2548 UINT8 *DevicePathPkg;\r
2549 UINT8 *CurrentDevicePath;\r
ae79d2f9 2550 BOOLEAN IfrDataParsedFlag;\r
93e3992d 2551\r
2552 if (This == NULL || Results == NULL) {\r
2553 return EFI_INVALID_PARAMETER;\r
2554 }\r
2555\r
84f9a9ec
LG
2556 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2557\r
93e3992d 2558 //\r
2559 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2560 // Results if this fix length is insufficient.\r
2561 //\r
2562 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2563 if (*Results == NULL) {\r
2564 return EFI_OUT_OF_RESOURCES;\r
2565 }\r
2566\r
8d00a0f1 2567 NumberConfigAccessHandles = 0;\r
2568 Status = gBS->LocateHandleBuffer (\r
2569 ByProtocol,\r
2570 &gEfiHiiConfigAccessProtocolGuid,\r
2571 NULL,\r
2572 &NumberConfigAccessHandles,\r
2573 &ConfigAccessHandles\r
2574 );\r
2575 if (EFI_ERROR (Status)) {\r
2576 return Status;\r
2577 }\r
93e3992d 2578\r
8d00a0f1 2579 FirstElement = TRUE;\r
93e3992d 2580\r
8d00a0f1 2581 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 2582 Status = gBS->HandleProtocol (\r
8d00a0f1 2583 ConfigAccessHandles[Index],\r
93e3992d 2584 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 2585 (VOID **) &ConfigAccess\r
93e3992d 2586 );\r
8d00a0f1 2587 if (EFI_ERROR (Status)) {\r
2588 continue;\r
2589 }\r
93e3992d 2590\r
84f9a9ec
LG
2591 //\r
2592 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
2593 //\r
ae79d2f9 2594 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
2595 Progress = NULL;\r
2596 HiiHandle = NULL;\r
84f9a9ec 2597 DefaultResults = NULL;\r
8567300a 2598 Database = NULL;\r
ae79d2f9 2599 ConfigRequest = NULL;\r
84f9a9ec 2600 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
2601 if (DevicePath != NULL) {\r
2602 for (Link = Private->DatabaseList.ForwardLink;\r
2603 Link != &Private->DatabaseList;\r
2604 Link = Link->ForwardLink\r
2605 ) {\r
2606 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2607 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2608 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2609 if (CompareMem (\r
84f9a9ec
LG
2610 DevicePath,\r
2611 CurrentDevicePath,\r
6e3f5b2a
LG
2612 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2613 ) == 0) {\r
84f9a9ec
LG
2614 HiiHandle = Database->Handle;\r
2615 break;\r
2616 }\r
2617 }\r
2618 }\r
2619 }\r
2620\r
93e3992d 2621 Status = ConfigAccess->ExtractConfig (\r
2622 ConfigAccess,\r
6e3f5b2a 2623 NULL,\r
84f9a9ec 2624 &Progress,\r
93e3992d 2625 &AccessResults\r
2626 );\r
ae79d2f9 2627 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
2628 //\r
2629 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2630 //\r
2631 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
2632 IfrDataParsedFlag = TRUE;\r
2633 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
2634 //\r
2635 // Get the full request string to get the Current setting again.\r
2636 //\r
2637 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
2638 Status = ConfigAccess->ExtractConfig (\r
2639 ConfigAccess,\r
2640 ConfigRequest,\r
2641 &Progress,\r
2642 &AccessResults\r
2643 );\r
2644 FreePool (ConfigRequest);\r
2645 } else {\r
2646 Status = EFI_NOT_FOUND;\r
2647 }\r
2648 }\r
2649 }\r
2650\r
2651 if (!EFI_ERROR (Status)) {\r
2652 //\r
2653 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
2654 //\r
2655 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
2656 StringPtr = StrStr (AccessResults, L"&GUID=");\r
2657 if (StringPtr != NULL) {\r
2658 *StringPtr = 0;\r
2659 }\r
2660 if (StrStr (AccessResults, L"&OFFSET=") != NULL) {\r
ae79d2f9
LG
2661 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
2662 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
2663 }\r
2664 if (StringPtr != NULL) {\r
2665 *StringPtr = L'&';\r
2666 }\r
2667 }\r
84f9a9ec
LG
2668 //\r
2669 // Merge the default sting from IFR code into the got setting from driver.\r
2670 //\r
2671 if (DefaultResults != NULL) {\r
8567300a
LG
2672 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
2673 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 2674 FreePool (DefaultResults);\r
8567300a 2675 DefaultResults = NULL;\r
84f9a9ec
LG
2676 }\r
2677 \r
8d00a0f1 2678 //\r
2679 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
2680 // which seperates the first <ConfigAltResp> and the following ones. \r
2681 //\r
2682 if (!FirstElement) {\r
2683 Status = AppendToMultiString (Results, L"&");\r
2684 ASSERT_EFI_ERROR (Status);\r
676df92c 2685 }\r
8d00a0f1 2686 \r
2687 Status = AppendToMultiString (Results, AccessResults);\r
2688 ASSERT_EFI_ERROR (Status);\r
93e3992d 2689\r
8d00a0f1 2690 FirstElement = FALSE;\r
2691 \r
2692 FreePool (AccessResults);\r
2693 AccessResults = NULL;\r
2694 }\r
93e3992d 2695 }\r
f4113e1f 2696 FreePool (ConfigAccessHandles);\r
93e3992d 2697\r
8d00a0f1 2698 return EFI_SUCCESS; \r
93e3992d 2699}\r
2700\r
2701\r
2702/**\r
2703 This function processes the results of processing forms and routes it to the\r
2704 appropriate handlers or storage.\r
2705\r
2706 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2707 instance.\r
2708 @param Configuration A null-terminated Unicode string in\r
2709 <MulltiConfigResp> format.\r
2710 @param Progress A pointer to a string filled in with the offset of\r
2711 the most recent & before the first failing name /\r
2712 value pair (or the beginning of the string if the\r
2713 failure is in the first name / value pair) or the\r
2714 terminating NULL if all was successful.\r
2715\r
2716 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
2717 distribution.\r
2718 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
2719 results that must be stored awaiting possible\r
2720 future protocols.\r
2721 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
2722 would result in this type of error.\r
2723 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
2724 found.\r
2725\r
2726**/\r
2727EFI_STATUS\r
2728EFIAPI\r
813acf3a 2729HiiConfigRoutingRouteConfig (\r
93e3992d 2730 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2731 IN CONST EFI_STRING Configuration,\r
2732 OUT EFI_STRING *Progress\r
2733 )\r
2734{\r
84f9a9ec 2735 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2736 EFI_STRING StringPtr;\r
2737 EFI_STRING ConfigResp;\r
2738 UINTN Length;\r
2739 EFI_STATUS Status;\r
2740 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 2741 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
2742 LIST_ENTRY *Link;\r
2743 HII_DATABASE_RECORD *Database;\r
2744 UINT8 *DevicePathPkg;\r
2745 UINT8 *CurrentDevicePath;\r
93e3992d 2746 EFI_HANDLE DriverHandle;\r
2747 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2748 EFI_STRING AccessProgress;\r
93e3992d 2749\r
2750 if (This == NULL || Progress == NULL) {\r
2751 return EFI_INVALID_PARAMETER;\r
2752 }\r
2753\r
2754 if (Configuration == NULL) {\r
2755 *Progress = NULL;\r
2756 return EFI_INVALID_PARAMETER;\r
2757 }\r
2758\r
84f9a9ec 2759 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 2760 StringPtr = Configuration;\r
2761 *Progress = StringPtr;\r
2762\r
2763 //\r
2764 // The first element of <MultiConfigResp> should be\r
2765 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
2766 //\r
2767 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2768 return EFI_INVALID_PARAMETER;\r
2769 }\r
2770\r
2771 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
2772 //\r
2773 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
2774 // or most recent & before the error.\r
2775 //\r
2776 if (StringPtr == Configuration) {\r
2777 *Progress = StringPtr;\r
2778 } else {\r
2779 *Progress = StringPtr - 1;\r
2780 }\r
2781\r
2782 //\r
2783 // Process each <ConfigResp> of <MultiConfigResp>\r
2784 //\r
2785 Length = CalculateConfigStringLen (StringPtr);\r
2786 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
2787 if (ConfigResp == NULL) {\r
2788 return EFI_OUT_OF_RESOURCES;\r
2789 }\r
2790 //\r
2791 // Append '\0' to the end of ConfigRequest\r
2792 //\r
2793 *(ConfigResp + Length) = 0;\r
2794\r
2795 //\r
2796 // Get the UEFI device path\r
2797 //\r
2798 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
2799 if (EFI_ERROR (Status)) {\r
676df92c 2800 FreePool (ConfigResp);\r
93e3992d 2801 return Status;\r
2802 }\r
2803\r
2804 //\r
84f9a9ec
LG
2805 // Find driver which matches the routing data.\r
2806 //\r
2807 DriverHandle = NULL;\r
84f9a9ec
LG
2808 for (Link = Private->DatabaseList.ForwardLink;\r
2809 Link != &Private->DatabaseList;\r
2810 Link = Link->ForwardLink\r
2811 ) {\r
2812 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2813\r
2814 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
2815 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 2816 if (CompareMem (\r
84f9a9ec
LG
2817 DevicePath,\r
2818 CurrentDevicePath,\r
6e3f5b2a
LG
2819 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
2820 ) == 0) {\r
84f9a9ec
LG
2821 DriverHandle = Database->DriverHandle;\r
2822 break;\r
2823 }\r
2824 }\r
2825 }\r
93e3992d 2826\r
84f9a9ec
LG
2827 //\r
2828 // Try to find driver handle by device path.\r
2829 //\r
2830 if (DriverHandle == NULL) {\r
2831 TempDevicePath = DevicePath;\r
2832 Status = gBS->LocateDevicePath (\r
2833 &gEfiDevicePathProtocolGuid,\r
2834 &TempDevicePath,\r
2835 &DriverHandle\r
2836 );\r
2837 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2838 //\r
2839 // Routing data does not match any known driver.\r
2840 // Set Progress to the 'G' in "GUID" of the routing header.\r
2841 //\r
2842 FreePool (DevicePath);\r
2843 *Progress = StringPtr;\r
2844 FreePool (ConfigResp);\r
2845 return EFI_NOT_FOUND;\r
2846 }\r
93e3992d 2847 }\r
2848\r
84f9a9ec
LG
2849 FreePool (DevicePath);\r
2850\r
93e3992d 2851 //\r
2852 // Call corresponding ConfigAccess protocol to route settings\r
2853 //\r
2854 Status = gBS->HandleProtocol (\r
2855 DriverHandle,\r
2856 &gEfiHiiConfigAccessProtocolGuid,\r
2857 (VOID **) &ConfigAccess\r
2858 );\r
2859 ASSERT_EFI_ERROR (Status);\r
2860\r
2861 Status = ConfigAccess->RouteConfig (\r
2862 ConfigAccess,\r
2863 ConfigResp,\r
2864 &AccessProgress\r
2865 );\r
2866\r
2867 if (EFI_ERROR (Status)) {\r
2868 //\r
2869 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
2870 // Map it to the progress on <MultiConfigResp> then return it.\r
2871 //\r
8d00a0f1 2872 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 2873\r
676df92c 2874 FreePool (ConfigResp);\r
93e3992d 2875 return Status;\r
2876 }\r
2877\r
676df92c 2878 FreePool (ConfigResp);\r
93e3992d 2879 ConfigResp = NULL;\r
2880\r
2881 //\r
2882 // Go to next <ConfigResp> (skip '&').\r
2883 //\r
2884 StringPtr += Length;\r
2885 if (*StringPtr == 0) {\r
2886 *Progress = StringPtr;\r
2887 break;\r
2888 }\r
2889\r
2890 StringPtr++;\r
2891\r
2892 }\r
2893\r
2894 return EFI_SUCCESS;\r
93e3992d 2895}\r
2896\r
2897\r
2898/**\r
2899 This helper function is to be called by drivers to map configuration data\r
2900 stored in byte array ("block") formats such as UEFI Variables into current\r
2901 configuration strings.\r
2902\r
2903 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
2904 instance.\r
2905 @param ConfigRequest A null-terminated Unicode string in\r
2906 <ConfigRequest> format.\r
2907 @param Block Array of bytes defining the block's configuration.\r
2908 @param BlockSize Length in bytes of Block.\r
2909 @param Config Filled-in configuration string. String allocated\r
2910 by the function. Returned only if call is\r
84f9a9ec 2911 successful. It is <ConfigResp> string format.\r
93e3992d 2912 @param Progress A pointer to a string filled in with the offset of\r
2913 the most recent & before the first failing\r
2914 name/value pair (or the beginning of the string if\r
2915 the failure is in the first name / value pair) or\r
2916 the terminating NULL if all was successful.\r
2917\r
2918 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
2919 terminator at the end of the ConfigRequest\r
2920 string.\r
2921 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
2922 points to the first character of ConfigRequest.\r
2923 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
2924 Block parameter would result in this type of\r
2925 error. Progress points to the first character of\r
2926 ConfigRequest.\r
2927 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
2928 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
2929 Block is left updated and Progress points at\r
2930 the "&" preceding the first non-<BlockName>.\r
2931\r
2932**/\r
2933EFI_STATUS\r
2934EFIAPI\r
2935HiiBlockToConfig (\r
2936 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
2937 IN CONST EFI_STRING ConfigRequest,\r
2938 IN CONST UINT8 *Block,\r
2939 IN CONST UINTN BlockSize,\r
2940 OUT EFI_STRING *Config,\r
2941 OUT EFI_STRING *Progress\r
2942 )\r
2943{\r
84f9a9ec 2944 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 2945 EFI_STRING StringPtr;\r
2946 UINTN Length;\r
2947 EFI_STATUS Status;\r
2948 EFI_STRING TmpPtr;\r
2949 UINT8 *TmpBuffer;\r
2950 UINTN Offset;\r
2951 UINTN Width;\r
2952 UINT8 *Value;\r
2953 EFI_STRING ValueStr;\r
2954 EFI_STRING ConfigElement;\r
63d55bb9
LG
2955 UINTN Index;\r
2956 UINT8 *TemBuffer;\r
2957 CHAR16 *TemString;\r
93e3992d 2958\r
2959 if (This == NULL || Progress == NULL || Config == NULL) {\r
2960 return EFI_INVALID_PARAMETER;\r
2961 }\r
2962\r
2963 if (Block == NULL || ConfigRequest == NULL) {\r
2964 *Progress = ConfigRequest;\r
2965 return EFI_INVALID_PARAMETER;\r
2966 }\r
2967\r
84f9a9ec
LG
2968\r
2969 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
2970 ASSERT (Private != NULL);\r
2971\r
93e3992d 2972 StringPtr = ConfigRequest;\r
2973 ValueStr = NULL;\r
2974 Value = NULL;\r
2975 ConfigElement = NULL;\r
2976\r
2977 //\r
2978 // Allocate a fix length of memory to store Results. Reallocate memory for\r
2979 // Results if this fix length is insufficient.\r
2980 //\r
2981 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
2982 if (*Config == NULL) {\r
2983 return EFI_OUT_OF_RESOURCES;\r
2984 }\r
2985\r
2986 //\r
2987 // Jump <ConfigHdr>\r
2988 //\r
2989 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2990 *Progress = StringPtr;\r
2991 Status = EFI_INVALID_PARAMETER;\r
2992 goto Exit;\r
2993 }\r
2994 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
2995 StringPtr++;\r
2996 }\r
2997 if (*StringPtr == 0) {\r
76c24251 2998 *Progress = StringPtr - 1;\r
93e3992d 2999 Status = EFI_INVALID_PARAMETER;\r
3000 goto Exit;\r
3001 }\r
08e6463a 3002\r
3003 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3004 StringPtr++;\r
3005 }\r
3006 if (*StringPtr == 0) {\r
76c24251 3007 *Progress = StringPtr - 1;\r
08e6463a 3008 Status = EFI_INVALID_PARAMETER;\r
3009 goto Exit;\r
3010 }\r
3011 //\r
3012 // Skip '&'\r
3013 //\r
3014 StringPtr++;\r
93e3992d 3015\r
3016 //\r
3017 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
3018 //\r
3019 Length = StringPtr - ConfigRequest;\r
3020 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
3021\r
3022 //\r
3023 // Parse each <RequestElement> if exists\r
3024 // Only <BlockName> format is supported by this help function.\r
3025 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
3026 //\r
3027 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
3028 //\r
3029 // Back up the header of one <BlockName>\r
3030 //\r
3031 TmpPtr = StringPtr;\r
3032\r
3033 StringPtr += StrLen (L"OFFSET=");\r
3034 //\r
3035 // Get Offset\r
3036 //\r
3037 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3038 if (Status == EFI_OUT_OF_RESOURCES) {\r
3039 *Progress = ConfigRequest;\r
3040 goto Exit;\r
3041 }\r
3042 Offset = 0;\r
3043 CopyMem (\r
3044 &Offset,\r
3045 TmpBuffer,\r
3046 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3047 );\r
676df92c 3048 FreePool (TmpBuffer);\r
93e3992d 3049\r
3050 StringPtr += Length;\r
3051 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3052 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
3053 Status = EFI_INVALID_PARAMETER;\r
3054 goto Exit;\r
3055 }\r
3056 StringPtr += StrLen (L"&WIDTH=");\r
3057\r
3058 //\r
3059 // Get Width\r
3060 //\r
3061 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3062 if (Status == EFI_OUT_OF_RESOURCES) {\r
3063 *Progress = ConfigRequest;\r
3064 goto Exit;\r
3065 }\r
3066 Width = 0;\r
3067 CopyMem (\r
3068 &Width,\r
3069 TmpBuffer,\r
3070 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3071 );\r
676df92c 3072 FreePool (TmpBuffer);\r
93e3992d 3073\r
3074 StringPtr += Length;\r
3075 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3076 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3077 Status = EFI_INVALID_PARAMETER;\r
3078 goto Exit;\r
3079 }\r
3080\r
3081 //\r
3082 // Calculate Value and convert it to hex string.\r
3083 //\r
3084 if (Offset + Width > BlockSize) {\r
3085 *Progress = StringPtr;\r
3086 Status = EFI_DEVICE_ERROR;\r
3087 goto Exit;\r
3088 }\r
3089\r
3090 Value = (UINT8 *) AllocateZeroPool (Width);\r
3091 if (Value == NULL) {\r
3092 *Progress = ConfigRequest;\r
3093 Status = EFI_OUT_OF_RESOURCES;\r
3094 goto Exit;\r
3095 }\r
3096\r
3097 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
3098\r
3099 Length = Width * 2 + 1;\r
3100 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
3101 if (ValueStr == NULL) {\r
3102 *Progress = ConfigRequest;\r
3103 Status = EFI_OUT_OF_RESOURCES;\r
3104 goto Exit;\r
3105 }\r
63d55bb9
LG
3106 \r
3107 TemString = ValueStr;\r
3108 TemBuffer = Value + Width - 1;\r
3109 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
3110 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
3111 }\r
813acf3a 3112\r
676df92c 3113 FreePool (Value);\r
93e3992d 3114 Value = NULL;\r
3115\r
3116 //\r
3117 // Build a ConfigElement\r
3118 //\r
3119 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
3120 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
3121 if (ConfigElement == NULL) {\r
3122 Status = EFI_OUT_OF_RESOURCES;\r
3123 goto Exit;\r
3124 }\r
3125 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
3126 if (*StringPtr == 0) {\r
3127 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
3128 }\r
3129 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
3130 StrCat (ConfigElement, L"VALUE=");\r
3131 StrCat (ConfigElement, ValueStr);\r
3132\r
3133 AppendToMultiString (Config, ConfigElement);\r
3134\r
676df92c 3135 FreePool (ConfigElement);\r
3136 FreePool (ValueStr);\r
93e3992d 3137 ConfigElement = NULL;\r
3138 ValueStr = NULL;\r
3139\r
3140 //\r
3141 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
3142 //\r
3143 if (*StringPtr == 0) {\r
3144 break;\r
3145 }\r
3146 AppendToMultiString (Config, L"&");\r
3147 StringPtr++;\r
3148\r
3149 }\r
3150\r
3151 if (*StringPtr != 0) {\r
3152 *Progress = StringPtr - 1;\r
3153 Status = EFI_INVALID_PARAMETER;\r
3154 goto Exit;\r
3155 }\r
84f9a9ec
LG
3156 \r
3157 HiiToLower (*Config);\r
93e3992d 3158 *Progress = StringPtr;\r
3159 return EFI_SUCCESS;\r
3160\r
3161Exit:\r
76c24251 3162 if (*Config != NULL) {\r
1f1cb2f2
LG
3163 FreePool (*Config);\r
3164 *Config = NULL;\r
76c24251 3165 }\r
676df92c 3166 if (ValueStr != NULL) {\r
3167 FreePool (ValueStr);\r
3168 }\r
3169 if (Value != NULL) {\r
3170 FreePool (Value);\r
3171 }\r
69367b5b 3172 if (ConfigElement != NULL) {\r
676df92c 3173 FreePool (ConfigElement);\r
3174 }\r
93e3992d 3175\r
3176 return Status;\r
3177\r
3178}\r
3179\r
3180\r
3181/**\r
3182 This helper function is to be called by drivers to map configuration strings\r
3183 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
3184\r
3185 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3186 instance.\r
3187 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
84f9a9ec 3188 format. It can be ConfigAltResp format string.\r
93e3992d 3189 @param Block A possibly null array of bytes representing the\r
3190 current block. Only bytes referenced in the\r
3191 ConfigResp string in the block are modified. If\r
3192 this parameter is null or if the *BlockSize\r
3193 parameter is (on input) shorter than required by\r
3194 the Configuration string, only the BlockSize\r
3195 parameter is updated and an appropriate status\r
3196 (see below) is returned.\r
3197 @param BlockSize The length of the Block in units of UINT8. On\r
3198 input, this is the size of the Block. On output,\r
3199 if successful, contains the index of the last\r
3200 modified byte in the Block.\r
3201 @param Progress On return, points to an element of the ConfigResp\r
3202 string filled in with the offset of the most\r
3203 recent '&' before the first failing name / value\r
3204 pair (or the beginning of the string if the\r
3205 failure is in the first name / value pair) or the\r
3206 terminating NULL if all was successful.\r
3207\r
3208 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
3209 terminator at the end of the ConfigResp string.\r
3210 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
3211 points to the first character of ConfigResp.\r
3212 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
3213 Block parameter would result in this type of\r
3214 error. Progress points to the first character of\r
3215 ConfigResp.\r
3216 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
3217 value pair. Block is left updated and\r
3218 Progress points at the '&' preceding the first\r
3219 non-<BlockName>.\r
3220\r
3221**/\r
3222EFI_STATUS\r
3223EFIAPI\r
3224HiiConfigToBlock (\r
3225 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3226 IN CONST EFI_STRING ConfigResp,\r
3227 IN OUT UINT8 *Block,\r
3228 IN OUT UINTN *BlockSize,\r
3229 OUT EFI_STRING *Progress\r
3230 )\r
3231{\r
3232 HII_DATABASE_PRIVATE_DATA *Private;\r
3233 EFI_STRING StringPtr;\r
3234 UINTN Length;\r
3235 EFI_STATUS Status;\r
3236 UINT8 *TmpBuffer;\r
3237 UINTN Offset;\r
3238 UINTN Width;\r
3239 UINT8 *Value;\r
3240 UINTN BufferSize;\r
3241\r
3242 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
3243 return EFI_INVALID_PARAMETER;\r
3244 }\r
3245\r
3246 if (ConfigResp == NULL || Block == NULL) {\r
3247 *Progress = ConfigResp;\r
3248 return EFI_INVALID_PARAMETER;\r
3249 }\r
3250\r
3251 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3252 ASSERT (Private != NULL);\r
3253\r
3254 StringPtr = ConfigResp;\r
3255 BufferSize = *BlockSize;\r
3256 Value = NULL;\r
3257\r
3258 //\r
3259 // Jump <ConfigHdr>\r
3260 //\r
3261 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3262 *Progress = StringPtr;\r
3263 Status = EFI_INVALID_PARAMETER;\r
3264 goto Exit;\r
3265 }\r
3266 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
3267 StringPtr++;\r
3268 }\r
3269 if (*StringPtr == 0) {\r
3270 *Progress = StringPtr;\r
3271 Status = EFI_INVALID_PARAMETER;\r
3272 goto Exit;\r
3273 }\r
08e6463a 3274\r
3275 while (*StringPtr != L'&' && *StringPtr != 0) {\r
3276 StringPtr++;\r
3277 }\r
3278 if (*StringPtr == 0) {\r
3279 *Progress = StringPtr;\r
3280 Status = EFI_INVALID_PARAMETER;\r
3281 goto Exit;\r
3282 }\r
3283 //\r
3284 // Skip '&'\r
3285 //\r
3286 StringPtr++;\r
93e3992d 3287\r
3288 //\r
3289 // Parse each <ConfigElement> if exists\r
3290 // Only <BlockConfig> format is supported by this help function.\r
3291 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
3292 //\r
3293 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
3294 StringPtr += StrLen (L"OFFSET=");\r
3295 //\r
3296 // Get Offset\r
3297 //\r
3298 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 3299 if (EFI_ERROR (Status)) {\r
93e3992d 3300 *Progress = ConfigResp;\r
3301 goto Exit;\r
3302 }\r
3303 Offset = 0;\r
3304 CopyMem (\r
3305 &Offset,\r
3306 TmpBuffer,\r
3307 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3308 );\r
676df92c 3309 FreePool (TmpBuffer);\r
93e3992d 3310\r
3311 StringPtr += Length;\r
3312 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3313 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
3314 Status = EFI_INVALID_PARAMETER;\r
3315 goto Exit;\r
3316 }\r
3317 StringPtr += StrLen (L"&WIDTH=");\r
3318\r
3319 //\r
3320 // Get Width\r
3321 //\r
3322 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3323 if (Status == EFI_OUT_OF_RESOURCES) {\r
3324 *Progress = ConfigResp;\r
3325 goto Exit;\r
3326 }\r
3327 Width = 0;\r
3328 CopyMem (\r
3329 &Width,\r
3330 TmpBuffer,\r
3331 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
3332 );\r
676df92c 3333 FreePool (TmpBuffer);\r
93e3992d 3334\r
3335 StringPtr += Length;\r
3336 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
3337 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
3338 Status = EFI_INVALID_PARAMETER;\r
3339 goto Exit;\r
3340 }\r
3341 StringPtr += StrLen (L"&VALUE=");\r
3342\r
3343 //\r
3344 // Get Value\r
3345 //\r
3346 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 3347 if (EFI_ERROR (Status)) {\r
93e3992d 3348 *Progress = ConfigResp;\r
3349 goto Exit;\r
3350 }\r
3351\r
3352 StringPtr += Length;\r
3353 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3354 *Progress = StringPtr - Length - 7;\r
3355 Status = EFI_INVALID_PARAMETER;\r
3356 goto Exit;\r
3357 }\r
3358\r
3359 //\r
3360 // Update the Block with configuration info\r
3361 //\r
3362\r
3363 if (Offset + Width > BufferSize) {\r
3364 return EFI_DEVICE_ERROR;\r
3365 }\r
3366\r
3367 CopyMem (Block + Offset, Value, Width);\r
3368 *BlockSize = Offset + Width - 1;\r
3369\r
676df92c 3370 FreePool (Value);\r
93e3992d 3371 Value = NULL;\r
3372\r
3373 //\r
3374 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
3375 //\r
3376 if (*StringPtr == 0) {\r
3377 break;\r
3378 }\r
3379\r
3380 StringPtr++;\r
3381 }\r
84f9a9ec
LG
3382 \r
3383 //\r
3384 // The input string is ConfigAltResp format.\r
3385 //\r
3386 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {\r
93e3992d 3387 *Progress = StringPtr - 1;\r
3388 Status = EFI_INVALID_PARAMETER;\r
3389 goto Exit;\r
3390 }\r
3391\r
6e3f5b2a 3392 *Progress = StringPtr + StrLen (StringPtr);\r
93e3992d 3393 return EFI_SUCCESS;\r
3394\r
3395Exit:\r
3396\r
676df92c 3397 if (Value != NULL) {\r
3398 FreePool (Value);\r
3399 }\r
93e3992d 3400 return Status;\r
3401}\r
3402\r
3403\r
3404/**\r
3405 This helper function is to be called by drivers to extract portions of\r
3406 a larger configuration string.\r
3407\r
3408 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3409 instance.\r
3410 @param Configuration A null-terminated Unicode string in\r
84f9a9ec 3411 <MultiConfigAltResp> format. It is <ConfigAltResp> format.\r
93e3992d 3412 @param Guid A pointer to the GUID value to search for in the\r
3413 routing portion of the ConfigResp string when\r
3414 retrieving the requested data. If Guid is NULL,\r
3415 then all GUID values will be searched for.\r
3416 @param Name A pointer to the NAME value to search for in the\r
3417 routing portion of the ConfigResp string when\r
3418 retrieving the requested data. If Name is NULL,\r
3419 then all Name values will be searched for.\r
3420 @param DevicePath A pointer to the PATH value to search for in the\r
3421 routing portion of the ConfigResp string when\r
3422 retrieving the requested data. If DevicePath is\r
3423 NULL, then all DevicePath values will be searched\r
3424 for.\r
3425 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
3426 routing portion of the ConfigResp string when\r
3427 retrieving the requested data. If this parameter\r
3428 is NULL, then the current setting will be\r
3429 retrieved.\r
3430 @param AltCfgResp A pointer to a buffer which will be allocated by\r
3431 the function which contains the retrieved string\r
3432 as requested. This buffer is only allocated if\r
84f9a9ec 3433 the call was successful. It is <ConfigResp> format.\r
93e3992d 3434\r
3435 @retval EFI_SUCCESS The request succeeded. The requested data was\r
3436 extracted and placed in the newly allocated\r
3437 AltCfgResp buffer.\r
3438 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
3439 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
3440 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
3441 found.\r
3442\r
3443**/\r
3444EFI_STATUS\r
3445EFIAPI\r
3446HiiGetAltCfg (\r
3447 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3448 IN CONST EFI_STRING Configuration,\r
3449 IN CONST EFI_GUID *Guid,\r
3450 IN CONST EFI_STRING Name,\r
3451 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3452 IN CONST UINT16 *AltCfgId,\r
3453 OUT EFI_STRING *AltCfgResp\r
3454 )\r
3455{\r
93e3992d 3456 EFI_STATUS Status;\r
3457 EFI_STRING StringPtr;\r
e90b081a 3458 EFI_STRING HdrStart;\r
3459 EFI_STRING HdrEnd;\r
93e3992d 3460 EFI_STRING TmpPtr;\r
3461 UINTN Length;\r
e90b081a 3462 EFI_STRING GuidStr;\r
3463 EFI_STRING NameStr;\r
3464 EFI_STRING PathStr;\r
3465 EFI_STRING AltIdStr;\r
3466 EFI_STRING Result;\r
3467 BOOLEAN GuidFlag;\r
3468 BOOLEAN NameFlag;\r
3469 BOOLEAN PathFlag;\r
3470\r
3471 HdrStart = NULL;\r
3472 HdrEnd = NULL;\r
3473 GuidStr = NULL;\r
3474 NameStr = NULL;\r
3475 PathStr = NULL;\r
3476 AltIdStr = NULL;\r
3477 Result = NULL;\r
3478 GuidFlag = FALSE;\r
3479 NameFlag = FALSE;\r
3480 PathFlag = FALSE;\r
93e3992d 3481\r
3482 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
3483 return EFI_INVALID_PARAMETER;\r
3484 }\r
3485\r
3486 StringPtr = Configuration;\r
3487 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3488 return EFI_INVALID_PARAMETER;\r
3489 }\r
3490\r
3491 //\r
3492 // Generate the sub string for later matching.\r
3493 //\r
813acf3a 3494 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 3495 GenerateSubStr (\r
3496 L"PATH=",\r
3497 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 3498 (VOID *) DevicePath,\r
3499 1,\r
93e3992d 3500 &PathStr\r
3501 );\r
3502 if (AltCfgId != NULL) {\r
813acf3a 3503 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 3504 }\r
3505 if (Name != NULL) {\r
813acf3a 3506 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 3507 } else {\r
813acf3a 3508 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 3509 }\r
3510\r
3511 while (*StringPtr != 0) {\r
3512 //\r
3513 // Try to match the GUID\r
3514 //\r
3515 if (!GuidFlag) {\r
3516 TmpPtr = StrStr (StringPtr, GuidStr);\r
3517 if (TmpPtr == NULL) {\r
3518 Status = EFI_NOT_FOUND;\r
3519 goto Exit;\r
3520 }\r
3521 HdrStart = TmpPtr;\r
3522\r
3523 //\r
3524 // Jump to <NameHdr>\r
3525 //\r
3526 if (Guid != NULL) {\r
3527 StringPtr = TmpPtr + StrLen (GuidStr);\r
3528 } else {\r
3529 StringPtr = StrStr (TmpPtr, L"NAME=");\r
3530 if (StringPtr == NULL) {\r
3531 Status = EFI_NOT_FOUND;\r
3532 goto Exit;\r
3533 }\r
3534 }\r
3535 GuidFlag = TRUE;\r
3536 }\r
3537\r
3538 //\r
3539 // Try to match the NAME\r
3540 //\r
3541 if (GuidFlag && !NameFlag) {\r
3542 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
3543 GuidFlag = FALSE;\r
3544 } else {\r
3545 //\r
3546 // Jump to <PathHdr>\r
3547 //\r
3548 if (Name != NULL) {\r
3549 StringPtr += StrLen (NameStr);\r
3550 } else {\r
3551 StringPtr = StrStr (StringPtr, L"PATH=");\r
3552 if (StringPtr == NULL) {\r
3553 Status = EFI_NOT_FOUND;\r
3554 goto Exit;\r
3555 }\r
3556 }\r
3557 NameFlag = TRUE;\r
3558 }\r
3559 }\r
3560\r
3561 //\r
3562 // Try to match the DevicePath\r
3563 //\r
3564 if (GuidFlag && NameFlag && !PathFlag) {\r
3565 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
3566 GuidFlag = FALSE;\r
3567 NameFlag = FALSE;\r
3568 } else {\r
3569 //\r
3570 // Jump to '&' before <DescHdr> or <ConfigBody>\r
3571 //\r
3572 if (DevicePath != NULL) {\r
3573 StringPtr += StrLen (PathStr);\r
3574 } else {\r
3575 StringPtr = StrStr (StringPtr, L"&");\r
3576 if (StringPtr == NULL) {\r
3577 Status = EFI_NOT_FOUND;\r
3578 goto Exit;\r
3579 }\r
84f9a9ec 3580 StringPtr ++;\r
93e3992d 3581 }\r
3582 PathFlag = TRUE;\r
84f9a9ec 3583 HdrEnd = StringPtr;\r
93e3992d 3584 }\r
3585 }\r
3586\r
3587 //\r
3588 // Try to match the AltCfgId\r
3589 //\r
3590 if (GuidFlag && NameFlag && PathFlag) {\r
3591 if (AltCfgId == NULL) {\r
3592 //\r
3593 // Return Current Setting when AltCfgId is NULL.\r
3594 //\r
3595 Status = OutputConfigBody (StringPtr, &Result);\r
3596 goto Exit;\r
3597 }\r
3598 //\r
3599 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
3600 //\r
3601 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
3602 GuidFlag = FALSE;\r
3603 NameFlag = FALSE;\r
3604 PathFlag = FALSE;\r
3605 } else {\r
84f9a9ec
LG
3606 //\r
3607 // Skip AltIdStr and &\r
3608 //\r
3609 StringPtr = StringPtr + StrLen (AltIdStr);\r
3610 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 3611 goto Exit;\r
3612 }\r
3613 }\r
3614 }\r
3615\r
3616 Status = EFI_NOT_FOUND;\r
3617\r
3618Exit:\r
76c24251 3619 *AltCfgResp = NULL;\r
bc166db3 3620 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 3621 //\r
3622 // Copy the <ConfigHdr> and <ConfigBody>\r
3623 //\r
84f9a9ec 3624 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 3625 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
3626 if (*AltCfgResp == NULL) {\r
3627 Status = EFI_OUT_OF_RESOURCES;\r
3628 } else {\r
3629 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
3630 StrCat (*AltCfgResp, Result);\r
3631 Status = EFI_SUCCESS;\r
3632 }\r
3633 }\r
3634\r
676df92c 3635 if (GuidStr != NULL) {\r
3636 FreePool (GuidStr);\r
3637 }\r
3638 if (NameStr != NULL) {\r
3639 FreePool (NameStr);\r
3640 }\r
3641 if (PathStr != NULL) {\r
3642 FreePool (PathStr);\r
3643 }\r
3644 if (AltIdStr != NULL) {\r
3645 FreePool (AltIdStr);\r
3646 }\r
3647 if (Result != NULL) {\r
3648 FreePool (Result);\r
3649 }\r
93e3992d 3650\r
3651 return Status;\r
3652\r
93e3992d 3653}\r
3654\r
36fe40c2 3655\r