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