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