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