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