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