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