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