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