]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
BaseTools:To generate string default type correctly in VfrCompiler
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
... / ...
CommitLineData
1/** @file\r
2Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
3\r
4Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
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
13**/\r
14\r
15\r
16#include "HiiDatabase.h"\r
17extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
18\r
19/**\r
20 Calculate the number of Unicode characters of the incoming Configuration string,\r
21 not including NULL terminator.\r
22\r
23 This is a internal function.\r
24\r
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
31UINTN\r
32CalculateConfigStringLen (\r
33 IN EFI_STRING String\r
34 )\r
35{\r
36 EFI_STRING TmpPtr;\r
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
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
47 // \r
48 TmpPtr = StrStr (String, L"&GUID=");\r
49 if (TmpPtr == NULL) {\r
50 return StrLen (String);\r
51 }\r
52\r
53 return (TmpPtr - String);\r
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
61 This is a internal function.\r
62\r
63 @param String UEFI configuration string\r
64 @param DevicePathData Binary of a UEFI device path.\r
65\r
66 @retval EFI_NOT_FOUND The device path is not invalid.\r
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
73EFI_STATUS\r
74GetDevicePath (\r
75 IN EFI_STRING String,\r
76 OUT UINT8 **DevicePathData\r
77 )\r
78{\r
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
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
99 //\r
100 // Check whether path data does exist.\r
101 //\r
102 String += StrLen (L"PATH=");\r
103 if (*String == 0) {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
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
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
119 }\r
120 \r
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
125 //\r
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
127 if (DevicePathBuffer == NULL) {\r
128 return EFI_OUT_OF_RESOURCES;\r
129 }\r
130 \r
131 //\r
132 // Convert DevicePath\r
133 //\r
134 ZeroMem (TemStr, sizeof (TemStr));\r
135 for (Index = 0; Index < Length; Index ++) {\r
136 TemStr[0] = PathHdr[Index];\r
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
144 \r
145 //\r
146 // Validate DevicePath\r
147 //\r
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;\r
149 while (!IsDevicePathEnd (DevicePath)) {\r
150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
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
159\r
160 //\r
161 // return the device path\r
162 //\r
163 *DevicePathData = DevicePathBuffer;\r
164 return EFI_SUCCESS;\r
165}\r
166\r
167/**\r
168 Converts the unicode character of the string from uppercase to lowercase.\r
169 This is a internal function.\r
170\r
171 @param ConfigString String to be converted\r
172\r
173**/\r
174VOID\r
175EFIAPI\r
176HiiToLower (\r
177 IN EFI_STRING ConfigString\r
178 )\r
179{\r
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
195 }\r
196 }\r
197\r
198 return;\r
199}\r
200\r
201/**\r
202 Generate a sub string then output it.\r
203\r
204 This is a internal function.\r
205\r
206 @param String A constant string which is the prefix of the to be\r
207 generated string, e.g. GUID=\r
208\r
209 @param BufferLen The length of the Buffer in bytes.\r
210\r
211 @param Buffer Points to a buffer which will be converted to be the \r
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
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
223VOID\r
224GenerateSubStr (\r
225 IN CONST EFI_STRING String,\r
226 IN UINTN BufferLen,\r
227 IN VOID *Buffer,\r
228 IN UINT8 Flag,\r
229 OUT EFI_STRING *SubStr\r
230 )\r
231{\r
232 UINTN Length;\r
233 EFI_STRING Str;\r
234 EFI_STRING StringHeader;\r
235 CHAR16 *TemString;\r
236 CHAR16 *TemName;\r
237 UINT8 *TemBuffer;\r
238 UINTN Index;\r
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
247 \r
248 //\r
249 // Header + Data + '&' + '\0'\r
250 //\r
251 Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
252 Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
253 ASSERT (Str != NULL);\r
254\r
255 StrCpyS (Str, Length, String);\r
256\r
257 StringHeader = Str + StrLen (String);\r
258 TemString = (CHAR16 *) StringHeader;\r
259\r
260 switch (Flag) {\r
261 case 1:\r
262 //\r
263 // Convert Buffer to Hex String in reverse order\r
264 //\r
265 TemBuffer = ((UINT8 *) Buffer);\r
266 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {\r
267 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
268 }\r
269 break;\r
270 case 2:\r
271 //\r
272 // Check buffer is enough\r
273 //\r
274 TemName = (CHAR16 *) Buffer;\r
275 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));\r
276 //\r
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
278 //\r
279 for (; *TemName != L'\0'; TemName++) {\r
280 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
281 }\r
282 break;\r
283 case 3:\r
284 //\r
285 // Convert Buffer to Hex String\r
286 //\r
287 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;\r
288 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {\r
289 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
290 }\r
291 break;\r
292 default:\r
293 break;\r
294 }\r
295\r
296 //\r
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
298 //\r
299 StrCatS (Str, Length, L"&"); \r
300 HiiToLower (Str);\r
301\r
302 *SubStr = Str;\r
303}\r
304\r
305\r
306/**\r
307 Retrieve the <ConfigBody> from String then output it.\r
308\r
309 This is a internal function.\r
310\r
311 @param String A sub string of a configuration string in\r
312 <MultiConfigAltResp> format.\r
313 @param ConfigBody Points to the output string. It's caller's\r
314 responsibility to free this buffer.\r
315\r
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
318 @retval EFI_SUCCESS All existing storage is exported.\r
319\r
320**/\r
321EFI_STATUS\r
322OutputConfigBody (\r
323 IN EFI_STRING String,\r
324 OUT EFI_STRING *ConfigBody\r
325 )\r
326{\r
327 EFI_STRING TmpPtr;\r
328 EFI_STRING Result;\r
329 UINTN Length;\r
330\r
331 if (String == NULL || ConfigBody == NULL) {\r
332 return EFI_INVALID_PARAMETER;\r
333 }\r
334 \r
335 //\r
336 // The setting information should start OFFSET, not ALTCFG.\r
337 //\r
338 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {\r
339 return EFI_INVALID_PARAMETER;\r
340 }\r
341\r
342 TmpPtr = StrStr (String, L"GUID=");\r
343 if (TmpPtr == NULL) {\r
344 //\r
345 // It is the last <ConfigResp> of the incoming configuration string.\r
346 //\r
347 Result = AllocateCopyPool (StrSize (String), String);\r
348 if (Result == NULL) {\r
349 return EFI_OUT_OF_RESOURCES;\r
350 } else {\r
351 *ConfigBody = Result;\r
352 return EFI_SUCCESS;\r
353 }\r
354 }\r
355\r
356 Length = TmpPtr - String;\r
357 if (Length == 0) {\r
358 return EFI_NOT_FOUND;\r
359 }\r
360 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
361 if (Result == NULL) {\r
362 return EFI_OUT_OF_RESOURCES;\r
363 }\r
364\r
365 *(Result + Length - 1) = 0;\r
366 *ConfigBody = Result;\r
367 return EFI_SUCCESS;\r
368}\r
369\r
370/**\r
371 Append a string to a multi-string format.\r
372\r
373 This is a internal function.\r
374\r
375 @param MultiString String in <MultiConfigRequest>,\r
376 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
377 input, the buffer length of this string is\r
378 MAX_STRING_LENGTH. On output, the buffer length\r
379 might be updated.\r
380 @param AppendString NULL-terminated Unicode string.\r
381\r
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
384\r
385**/\r
386EFI_STATUS\r
387AppendToMultiString (\r
388 IN OUT EFI_STRING *MultiString,\r
389 IN EFI_STRING AppendString\r
390 )\r
391{\r
392 UINTN AppendStringSize;\r
393 UINTN MultiStringSize;\r
394 UINTN MaxLen;\r
395\r
396 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
397 return EFI_INVALID_PARAMETER;\r
398 }\r
399\r
400 AppendStringSize = StrSize (AppendString);\r
401 MultiStringSize = StrSize (*MultiString);\r
402 MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);\r
403\r
404 //\r
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
406 //\r
407 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
408 MultiStringSize > MAX_STRING_LENGTH) {\r
409 *MultiString = (EFI_STRING) ReallocatePool (\r
410 MultiStringSize,\r
411 MultiStringSize + AppendStringSize,\r
412 (VOID *) (*MultiString)\r
413 );\r
414 MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);\r
415 ASSERT (*MultiString != NULL);\r
416 }\r
417 //\r
418 // Append the incoming string\r
419 //\r
420 StrCatS (*MultiString, MaxLen, AppendString);\r
421\r
422 return EFI_SUCCESS;\r
423}\r
424\r
425\r
426/**\r
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
428 or WIDTH or VALUE.\r
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
430\r
431 This is a internal function.\r
432\r
433 @param StringPtr String in <BlockConfig> format and points to the\r
434 first character of <Number>.\r
435 @param Number The output value. Caller takes the responsibility\r
436 to free memory.\r
437 @param Len Length of the <Number>, in characters.\r
438\r
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
440 structures.\r
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
442 successfully.\r
443\r
444**/\r
445EFI_STATUS\r
446GetValueOfNumber (\r
447 IN EFI_STRING StringPtr,\r
448 OUT UINT8 **Number,\r
449 OUT UINTN *Len\r
450 )\r
451{\r
452 EFI_STRING TmpPtr;\r
453 UINTN Length;\r
454 EFI_STRING Str;\r
455 UINT8 *Buf;\r
456 EFI_STATUS Status;\r
457 UINT8 DigitUint8;\r
458 UINTN Index;\r
459 CHAR16 TemStr[2];\r
460\r
461 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {\r
462 return EFI_INVALID_PARAMETER;\r
463 }\r
464\r
465 Buf = NULL;\r
466\r
467 TmpPtr = StringPtr;\r
468 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
469 StringPtr++;\r
470 }\r
471 *Len = StringPtr - TmpPtr;\r
472 Length = *Len + 1;\r
473\r
474 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
475 if (Str == NULL) {\r
476 Status = EFI_OUT_OF_RESOURCES;\r
477 goto Exit;\r
478 }\r
479 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
480 *(Str + *Len) = L'\0';\r
481\r
482 Length = (Length + 1) / 2;\r
483 Buf = (UINT8 *) AllocateZeroPool (Length);\r
484 if (Buf == NULL) {\r
485 Status = EFI_OUT_OF_RESOURCES;\r
486 goto Exit;\r
487 }\r
488 \r
489 Length = *Len;\r
490 ZeroMem (TemStr, sizeof (TemStr));\r
491 for (Index = 0; Index < Length; Index ++) {\r
492 TemStr[0] = Str[Length - Index - 1];\r
493 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
494 if ((Index & 1) == 0) {\r
495 Buf [Index/2] = DigitUint8;\r
496 } else {\r
497 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
498 }\r
499 }\r
500\r
501 *Number = Buf;\r
502 Status = EFI_SUCCESS;\r
503\r
504Exit:\r
505 if (Str != NULL) {\r
506 FreePool (Str);\r
507 }\r
508\r
509 return Status;\r
510}\r
511\r
512/**\r
513 This function merges DefaultAltCfgResp string into AltCfgResp string for\r
514 the missing AltCfgId in AltCfgResq.\r
515\r
516 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
517 <ConfigAltResp> format. The default value string \r
518 will be merged into it. \r
519 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
520 <MultiConfigAltResp> format. The default value \r
521 string may contain more than one ConfigAltResp\r
522 string for the different varstore buffer.\r
523\r
524 @retval EFI_SUCCESS The merged string returns.\r
525 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
526**/\r
527EFI_STATUS\r
528EFIAPI\r
529MergeDefaultString (\r
530 IN OUT EFI_STRING *AltCfgResp,\r
531 IN EFI_STRING DefaultAltCfgResp\r
532 )\r
533{\r
534 EFI_STRING StringPtrDefault;\r
535 EFI_STRING StringPtrEnd;\r
536 CHAR16 TempChar;\r
537 EFI_STRING StringPtr;\r
538 EFI_STRING AltConfigHdr;\r
539 UINTN HeaderLength;\r
540 UINTN SizeAltCfgResp;\r
541 UINTN MaxLen;\r
542 UINTN TotalSize;\r
543 \r
544 if (*AltCfgResp == NULL) {\r
545 return EFI_INVALID_PARAMETER;\r
546 }\r
547 \r
548 //\r
549 // Get the requestr ConfigHdr\r
550 //\r
551 SizeAltCfgResp = 0;\r
552 StringPtr = *AltCfgResp;\r
553 \r
554 //\r
555 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
556 //\r
557 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
558 return EFI_INVALID_PARAMETER;\r
559 }\r
560 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
561 StringPtr++;\r
562 }\r
563 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
564 StringPtr++;\r
565 }\r
566 if (*StringPtr == L'\0') {\r
567 return EFI_INVALID_PARAMETER;\r
568 }\r
569 StringPtr += StrLen (L"&PATH=");\r
570 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
571 StringPtr ++;\r
572 }\r
573 HeaderLength = StringPtr - *AltCfgResp;\r
574\r
575 //\r
576 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
577 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
578 //\r
579 MaxLen = 1 + HeaderLength + 8 + 4 + 1;\r
580 AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
581 if (AltConfigHdr == NULL) {\r
582 return EFI_OUT_OF_RESOURCES;\r
583 }\r
584 StrCpyS (AltConfigHdr, MaxLen, L"&");\r
585 StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);\r
586 StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");\r
587 HeaderLength = StrLen (AltConfigHdr);\r
588 \r
589 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
590 while (StringPtrDefault != NULL) {\r
591 //\r
592 // Get AltCfg Name\r
593 //\r
594 StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);\r
595 StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
596 \r
597 //\r
598 // Append the found default value string to the input AltCfgResp\r
599 // \r
600 if (StringPtr == NULL) {\r
601 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
602 SizeAltCfgResp = StrSize (*AltCfgResp);\r
603 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);\r
604 if (StringPtrEnd == NULL) {\r
605 //\r
606 // No more default string is found.\r
607 //\r
608 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
609 SizeAltCfgResp,\r
610 TotalSize,\r
611 (VOID *) (*AltCfgResp)\r
612 );\r
613 if (*AltCfgResp == NULL) {\r
614 FreePool (AltConfigHdr);\r
615 return EFI_OUT_OF_RESOURCES;\r
616 }\r
617 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);\r
618 break;\r
619 } else {\r
620 TempChar = *StringPtrEnd;\r
621 *StringPtrEnd = L'\0';\r
622 *AltCfgResp = (EFI_STRING) ReallocatePool (\r
623 SizeAltCfgResp,\r
624 TotalSize,\r
625 (VOID *) (*AltCfgResp)\r
626 );\r
627 if (*AltCfgResp == NULL) {\r
628 FreePool (AltConfigHdr);\r
629 return EFI_OUT_OF_RESOURCES;\r
630 }\r
631 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);\r
632 *StringPtrEnd = TempChar;\r
633 }\r
634 }\r
635 \r
636 //\r
637 // Find next AltCfg String\r
638 //\r
639 *(AltConfigHdr + HeaderLength) = L'\0';\r
640 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);\r
641 }\r
642 \r
643 FreePool (AltConfigHdr);\r
644 return EFI_SUCCESS; \r
645}\r
646\r
647/**\r
648 This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
649\r
650 @param BlockData The BlockData is updated to add new default value.\r
651 @param DefaultValueData The DefaultValue is added.\r
652\r
653**/\r
654VOID\r
655InsertDefaultValue (\r
656 IN IFR_BLOCK_DATA *BlockData,\r
657 IN IFR_DEFAULT_DATA *DefaultValueData\r
658 )\r
659{\r
660 LIST_ENTRY *Link;\r
661 IFR_DEFAULT_DATA *DefaultValueArray; \r
662 LIST_ENTRY *DefaultLink;\r
663 \r
664 DefaultLink = &BlockData->DefaultValueEntry;\r
665\r
666 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {\r
667 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
668 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
669 //\r
670 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.\r
671 //\r
672 if (DefaultValueData->Type > DefaultValueArray->Type) {\r
673 //\r
674 // Update the default value array in BlockData.\r
675 //\r
676 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
677 DefaultValueArray->Type = DefaultValueData->Type;\r
678 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;\r
679 }\r
680 return;\r
681 } \r
682 }\r
683\r
684 //\r
685 // Insert new default value data in tail.\r
686 //\r
687 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
688 ASSERT (DefaultValueArray != NULL);\r
689 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));\r
690 InsertTailList (Link, &DefaultValueArray->Entry);\r
691}\r
692\r
693/**\r
694 This function inserts new BlockData into the block link\r
695\r
696 @param BlockLink The list entry points to block array.\r
697 @param BlockData The point to BlockData is added.\r
698 \r
699**/\r
700VOID\r
701InsertBlockData (\r
702 IN LIST_ENTRY *BlockLink,\r
703 IN IFR_BLOCK_DATA **BlockData\r
704 )\r
705{\r
706 LIST_ENTRY *Link;\r
707 IFR_BLOCK_DATA *BlockArray;\r
708 IFR_BLOCK_DATA *BlockSingleData;\r
709\r
710 BlockSingleData = *BlockData;\r
711\r
712 if (BlockSingleData->Name != NULL) {\r
713 InsertTailList (BlockLink, &BlockSingleData->Entry);\r
714 return;\r
715 }\r
716\r
717 //\r
718 // Insert block data in its Offset and Width order.\r
719 //\r
720 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
721 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
722 if (BlockArray->Offset == BlockSingleData->Offset) {\r
723 if (BlockArray->Width > BlockSingleData->Width) {\r
724 //\r
725 // Insert this block data in the front of block array\r
726 //\r
727 InsertTailList (Link, &BlockSingleData->Entry);\r
728 return;\r
729 }\r
730\r
731 if (BlockArray->Width == BlockSingleData->Width) {\r
732 //\r
733 // The same block array has been added.\r
734 //\r
735 if (BlockSingleData != BlockArray) {\r
736 FreePool (BlockSingleData);\r
737 *BlockData = BlockArray;\r
738 }\r
739 return;\r
740 }\r
741 } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
742 //\r
743 // Insert new 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 \r
750 //\r
751 // Add new block data into the tail.\r
752 //\r
753 InsertTailList (Link, &BlockSingleData->Entry); \r
754}\r
755\r
756/**\r
757 Retrieves a pointer to the a Null-terminated ASCII string containing the list \r
758 of languages that an HII handle in the HII Database supports. The returned \r
759 string is allocated using AllocatePool(). The caller is responsible for freeing\r
760 the returned string using FreePool(). The format of the returned string follows\r
761 the language format assumed the HII Database.\r
762 \r
763 If HiiHandle is NULL, then ASSERT().\r
764\r
765 @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
766\r
767 @retval NULL HiiHandle is not registered in the HII database\r
768 @retval NULL There are not enough resources available to retrieve the suported \r
769 languages.\r
770 @retval NULL The list of suported languages could not be retrieved.\r
771 @retval Other A pointer to the Null-terminated ASCII string of supported languages.\r
772\r
773**/\r
774CHAR8 *\r
775GetSupportedLanguages (\r
776 IN EFI_HII_HANDLE HiiHandle\r
777 )\r
778{\r
779 EFI_STATUS Status;\r
780 UINTN LanguageSize;\r
781 CHAR8 TempSupportedLanguages;\r
782 CHAR8 *SupportedLanguages;\r
783\r
784 ASSERT (HiiHandle != NULL);\r
785\r
786 //\r
787 // Retrieve the size required for the supported languages buffer.\r
788 //\r
789 LanguageSize = 0;\r
790 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);\r
791\r
792 //\r
793 // If GetLanguages() returns EFI_SUCCESS for a zero size, \r
794 // then there are no supported languages registered for HiiHandle. If GetLanguages() \r
795 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
796 // in the HII Database\r
797 //\r
798 if (Status != EFI_BUFFER_TOO_SMALL) {\r
799 //\r
800 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database\r
801 //\r
802 return NULL;\r
803 }\r
804\r
805 //\r
806 // Allocate the supported languages buffer.\r
807 //\r
808 SupportedLanguages = AllocateZeroPool (LanguageSize);\r
809 if (SupportedLanguages == NULL) {\r
810 //\r
811 // Return NULL if allocation fails.\r
812 //\r
813 return NULL;\r
814 }\r
815\r
816 //\r
817 // Retrieve the supported languages string\r
818 //\r
819 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);\r
820 if (EFI_ERROR (Status)) {\r
821 //\r
822 // Free the buffer and return NULL if the supported languages can not be retrieved.\r
823 //\r
824 FreePool (SupportedLanguages);\r
825 return NULL;\r
826 }\r
827\r
828 //\r
829 // Return the Null-terminated ASCII string of supported languages\r
830 //\r
831 return SupportedLanguages;\r
832}\r
833\r
834/**\r
835 Retrieves a string from a string package.\r
836 \r
837 If HiiHandle is NULL, then ASSERT().\r
838 If StringId is 0, then ASSET.\r
839\r
840 @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
841 @param[in] StringId The identifier of the string to retrieved from the string \r
842 package associated with HiiHandle.\r
843\r
844 @retval NULL The string specified by StringId is not present in the string package.\r
845 @retval Other The string was returned.\r
846\r
847**/\r
848EFI_STRING\r
849InternalGetString (\r
850 IN EFI_HII_HANDLE HiiHandle,\r
851 IN EFI_STRING_ID StringId\r
852 )\r
853{\r
854 EFI_STATUS Status;\r
855 UINTN StringSize;\r
856 CHAR16 TempString;\r
857 EFI_STRING String;\r
858 CHAR8 *SupportedLanguages;\r
859 CHAR8 *PlatformLanguage;\r
860 CHAR8 *BestLanguage;\r
861 CHAR8 *Language;\r
862\r
863 ASSERT (HiiHandle != NULL);\r
864 ASSERT (StringId != 0);\r
865\r
866 //\r
867 // Initialize all allocated buffers to NULL\r
868 // \r
869 SupportedLanguages = NULL;\r
870 PlatformLanguage = NULL;\r
871 BestLanguage = NULL;\r
872 String = NULL;\r
873 Language = "";\r
874\r
875 //\r
876 // Get the languages that the package specified by HiiHandle supports\r
877 //\r
878 SupportedLanguages = GetSupportedLanguages (HiiHandle);\r
879 if (SupportedLanguages == NULL) {\r
880 goto Error;\r
881 }\r
882\r
883 //\r
884 // Get the current platform language setting\r
885 //\r
886 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);\r
887\r
888 //\r
889 // Get the best matching language from SupportedLanguages\r
890 //\r
891 BestLanguage = GetBestLanguage (\r
892 SupportedLanguages, \r
893 FALSE, // RFC 4646 mode\r
894 Language, // Highest priority \r
895 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority\r
896 SupportedLanguages, // Lowest priority \r
897 NULL\r
898 );\r
899 if (BestLanguage == NULL) {\r
900 goto Error;\r
901 }\r
902\r
903 //\r
904 // Retrieve the size of the string in the string package for the BestLanguage\r
905 //\r
906 StringSize = 0;\r
907 Status = mPrivate.HiiString.GetString (\r
908 &mPrivate.HiiString,\r
909 BestLanguage,\r
910 HiiHandle,\r
911 StringId,\r
912 &TempString,\r
913 &StringSize,\r
914 NULL\r
915 );\r
916 //\r
917 // If GetString() returns EFI_SUCCESS for a zero size, \r
918 // then there are no supported languages registered for HiiHandle. If GetString() \r
919 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
920 // in the HII Database\r
921 //\r
922 if (Status != EFI_BUFFER_TOO_SMALL) {\r
923 goto Error;\r
924 }\r
925\r
926 //\r
927 // Allocate a buffer for the return string\r
928 //\r
929 String = AllocateZeroPool (StringSize);\r
930 if (String == NULL) {\r
931 goto Error;\r
932 }\r
933\r
934 //\r
935 // Retrieve the string from the string package\r
936 //\r
937 Status = mPrivate.HiiString.GetString (\r
938 &mPrivate.HiiString,\r
939 BestLanguage,\r
940 HiiHandle,\r
941 StringId,\r
942 String,\r
943 &StringSize,\r
944 NULL\r
945 );\r
946 if (EFI_ERROR (Status)) {\r
947 //\r
948 // Free the buffer and return NULL if the supported languages can not be retrieved.\r
949 //\r
950 FreePool (String);\r
951 String = NULL;\r
952 }\r
953\r
954Error:\r
955 //\r
956 // Free allocated buffers\r
957 //\r
958 if (SupportedLanguages != NULL) {\r
959 FreePool (SupportedLanguages);\r
960 }\r
961 if (PlatformLanguage != NULL) {\r
962 FreePool (PlatformLanguage);\r
963 }\r
964 if (BestLanguage != NULL) {\r
965 FreePool (BestLanguage);\r
966 }\r
967\r
968 //\r
969 // Return the Null-terminated Unicode string\r
970 //\r
971 return String;\r
972}\r
973\r
974/**\r
975 This function checks VarOffset and VarWidth is in the block range.\r
976\r
977 @param RequestBlockArray The block array is to be checked. \r
978 @param VarOffset Offset of var to the structure\r
979 @param VarWidth Width of var.\r
980 @param IsNameValueType Whether this varstore is name/value varstore or not.\r
981 @param HiiHandle Hii handle for this hii package.\r
982 \r
983 @retval TRUE This Var is in the block range.\r
984 @retval FALSE This Var is not in the block range.\r
985**/\r
986BOOLEAN\r
987BlockArrayCheck (\r
988 IN IFR_BLOCK_DATA *RequestBlockArray,\r
989 IN UINT16 VarOffset,\r
990 IN UINT16 VarWidth,\r
991 IN BOOLEAN IsNameValueType,\r
992 IN EFI_HII_HANDLE HiiHandle\r
993 )\r
994{\r
995 LIST_ENTRY *Link;\r
996 IFR_BLOCK_DATA *BlockData;\r
997 EFI_STRING Name;\r
998\r
999 //\r
1000 // No Request Block array, all vars are got.\r
1001 //\r
1002 if (RequestBlockArray == NULL) {\r
1003 return TRUE;\r
1004 }\r
1005\r
1006 //\r
1007 // Check the input var is in the request block range.\r
1008 //\r
1009 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
1010 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1011\r
1012 if (IsNameValueType) {\r
1013 Name = InternalGetString (HiiHandle, VarOffset);\r
1014 ASSERT (Name != NULL);\r
1015\r
1016 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {\r
1017 FreePool (Name);\r
1018 return TRUE;\r
1019 }\r
1020 FreePool (Name);\r
1021 } else {\r
1022 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
1023 return TRUE;\r
1024 }\r
1025 }\r
1026 }\r
1027\r
1028 return FALSE;\r
1029}\r
1030\r
1031/**\r
1032 Get form package data from data base.\r
1033\r
1034 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
1035 @param HiiFormPackage The buffer saves the package data.\r
1036 @param PackageSize The buffer size of the package data.\r
1037\r
1038**/\r
1039EFI_STATUS\r
1040GetFormPackageData (\r
1041 IN HII_DATABASE_RECORD *DataBaseRecord,\r
1042 IN OUT UINT8 **HiiFormPackage,\r
1043 OUT UINTN *PackageSize\r
1044 )\r
1045{\r
1046 EFI_STATUS Status;\r
1047 UINTN Size;\r
1048 UINTN ResultSize;\r
1049\r
1050 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {\r
1051 return EFI_INVALID_PARAMETER;\r
1052 }\r
1053\r
1054 Size = 0;\r
1055 ResultSize = 0;\r
1056 //\r
1057 // 0. Get Hii Form Package by HiiHandle\r
1058 //\r
1059 Status = ExportFormPackages (\r
1060 &mPrivate, \r
1061 DataBaseRecord->Handle, \r
1062 DataBaseRecord->PackageList, \r
1063 0, \r
1064 Size, \r
1065 HiiFormPackage,\r
1066 &ResultSize\r
1067 );\r
1068 if (EFI_ERROR (Status)) {\r
1069 return Status;\r
1070 }\r
1071 \r
1072 (*HiiFormPackage) = AllocatePool (ResultSize);\r
1073 if (*HiiFormPackage == NULL) {\r
1074 Status = EFI_OUT_OF_RESOURCES;\r
1075 return Status;\r
1076 }\r
1077\r
1078 //\r
1079 // Get HiiFormPackage by HiiHandle\r
1080 //\r
1081 Size = ResultSize;\r
1082 ResultSize = 0;\r
1083 Status = ExportFormPackages (\r
1084 &mPrivate, \r
1085 DataBaseRecord->Handle, \r
1086 DataBaseRecord->PackageList, \r
1087 0,\r
1088 Size, \r
1089 *HiiFormPackage,\r
1090 &ResultSize\r
1091 );\r
1092 if (EFI_ERROR (Status)) {\r
1093 FreePool (*HiiFormPackage);\r
1094 }\r
1095 \r
1096 *PackageSize = Size;\r
1097\r
1098 return Status;\r
1099}\r
1100\r
1101\r
1102/**\r
1103 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
1104\r
1105 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
1106 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1107 the first found varstore will be as ConfigHdr.\r
1108 @param IsEfiVarstore Whether the request storage type is efi varstore type.\r
1109 @param EfiVarStore The efi varstore info which will return.\r
1110**/ \r
1111EFI_STATUS\r
1112GetVarStoreType (\r
1113 IN HII_DATABASE_RECORD *DataBaseRecord,\r
1114 IN EFI_STRING ConfigHdr,\r
1115 OUT BOOLEAN *IsEfiVarstore,\r
1116 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore\r
1117 )\r
1118{\r
1119 EFI_STATUS Status;\r
1120 UINTN IfrOffset;\r
1121 UINTN PackageOffset;\r
1122 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1123 CHAR16 *VarStoreName;\r
1124 EFI_STRING GuidStr;\r
1125 EFI_STRING NameStr;\r
1126 EFI_STRING TempStr;\r
1127 UINTN LengthString; \r
1128 UINT8 *HiiFormPackage;\r
1129 UINTN PackageSize;\r
1130 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
1131 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
1132 \r
1133 HiiFormPackage = NULL;\r
1134 LengthString = 0;\r
1135 Status = EFI_SUCCESS;\r
1136 GuidStr = NULL;\r
1137 NameStr = NULL;\r
1138 TempStr = NULL;\r
1139 *IsEfiVarstore = FALSE;\r
1140\r
1141 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);\r
1142 if (EFI_ERROR (Status)) {\r
1143 return Status;\r
1144 }\r
1145\r
1146 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1147 PackageOffset = IfrOffset;\r
1148 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;\r
1149\r
1150 while (IfrOffset < PackageSize) {\r
1151 //\r
1152 // More than one form packages exist.\r
1153 //\r
1154 if (PackageOffset >= PackageHeader->Length) {\r
1155 //\r
1156 // Process the new form package.\r
1157 //\r
1158 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1159 IfrOffset += PackageOffset;\r
1160 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);\r
1161 }\r
1162\r
1163 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);\r
1164 IfrOffset += IfrOpHdr->Length;\r
1165 PackageOffset += IfrOpHdr->Length;\r
1166\r
1167 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {\r
1168 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1169 //\r
1170 // If the length is small than the structure, this is from old efi \r
1171 // varstore definition. Old efi varstore get config directly from \r
1172 // GetVariable function.\r
1173 //\r
1174 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1175 continue;\r
1176 }\r
1177\r
1178 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
1179 if (VarStoreName == NULL) {\r
1180 Status = EFI_OUT_OF_RESOURCES;\r
1181 goto Done;\r
1182 }\r
1183 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);\r
1184\r
1185 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);\r
1186 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
1187 LengthString = StrLen (GuidStr);\r
1188 LengthString = LengthString + StrLen (NameStr) + 1;\r
1189 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1190 if (TempStr == NULL) {\r
1191 FreePool (GuidStr);\r
1192 FreePool (NameStr);\r
1193 FreePool (VarStoreName);\r
1194 Status = EFI_OUT_OF_RESOURCES;\r
1195 goto Done;\r
1196 }\r
1197 StrCpyS (TempStr, LengthString, GuidStr);\r
1198 StrCatS (TempStr, LengthString, NameStr);\r
1199 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1200 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);\r
1201 if (*EfiVarStore == NULL) {\r
1202 FreePool (VarStoreName);\r
1203 FreePool (GuidStr);\r
1204 FreePool (NameStr);\r
1205 FreePool (TempStr);\r
1206 Status = EFI_OUT_OF_RESOURCES;\r
1207 goto Done;\r
1208 }\r
1209 *IsEfiVarstore = TRUE;\r
1210 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);\r
1211 } \r
1212 \r
1213 //\r
1214 // Free alllocated temp string.\r
1215 //\r
1216 FreePool (VarStoreName);\r
1217 FreePool (GuidStr);\r
1218 FreePool (NameStr);\r
1219 FreePool (TempStr);\r
1220\r
1221 //\r
1222 // Already found the varstore, break;\r
1223 //\r
1224 if (*IsEfiVarstore) {\r
1225 break;\r
1226 }\r
1227 }\r
1228 }\r
1229Done:\r
1230 if (HiiFormPackage != NULL) {\r
1231 FreePool (HiiFormPackage);\r
1232 }\r
1233\r
1234 return Status;\r
1235}\r
1236\r
1237/**\r
1238 Check whether the ConfigRequest string has the request elements.\r
1239 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
1240 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
1241\r
1242 @param ConfigRequest The input config request string.\r
1243\r
1244 @retval TRUE The input include config request elements.\r
1245 @retval FALSE The input string not includes.\r
1246\r
1247**/\r
1248BOOLEAN\r
1249GetElementsFromRequest (\r
1250 IN EFI_STRING ConfigRequest\r
1251 )\r
1252{\r
1253 EFI_STRING TmpRequest;\r
1254\r
1255 TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
1256 ASSERT (TmpRequest != NULL);\r
1257\r
1258 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
1259 return TRUE;\r
1260 }\r
1261\r
1262 return FALSE;\r
1263}\r
1264\r
1265/**\r
1266 Check whether the this varstore is the request varstore.\r
1267\r
1268 @param VarstoreGuid Varstore guid.\r
1269 @param Name Varstore name.\r
1270 @param ConfigHdr Current configRequest info.\r
1271\r
1272 @retval TRUE This varstore is the requst one.\r
1273 @retval FALSE This varstore is not the requst one.\r
1274 \r
1275**/\r
1276BOOLEAN\r
1277IsThisVarstore (\r
1278 IN EFI_GUID *VarstoreGuid,\r
1279 IN CHAR16 *Name,\r
1280 IN CHAR16 *ConfigHdr\r
1281 )\r
1282{\r
1283 EFI_STRING GuidStr;\r
1284 EFI_STRING NameStr;\r
1285 EFI_STRING TempStr;\r
1286 UINTN LengthString;\r
1287 BOOLEAN RetVal;\r
1288\r
1289 RetVal = FALSE;\r
1290 GuidStr = NULL;\r
1291 TempStr = NULL;\r
1292\r
1293 //\r
1294 // If ConfigHdr has name field and varstore not has name, return FALSE.\r
1295 //\r
1296 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {\r
1297 return FALSE;\r
1298 }\r
1299\r
1300 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);\r
1301 if (Name != NULL) {\r
1302 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);\r
1303 } else {\r
1304 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
1305 }\r
1306 LengthString = StrLen (GuidStr);\r
1307 LengthString = LengthString + StrLen (NameStr) + 1;\r
1308 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
1309 if (TempStr == NULL) {\r
1310 goto Done;\r
1311 }\r
1312\r
1313 StrCpyS (TempStr, LengthString, GuidStr);\r
1314 StrCatS (TempStr, LengthString, NameStr);\r
1315\r
1316 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
1317 RetVal = TRUE;\r
1318 }\r
1319\r
1320Done:\r
1321 if (GuidStr != NULL) {\r
1322 FreePool (GuidStr); \r
1323 }\r
1324\r
1325 if (NameStr != NULL) {\r
1326 FreePool (NameStr);\r
1327 }\r
1328\r
1329 if (TempStr != NULL) {\r
1330 FreePool (TempStr);\r
1331 }\r
1332\r
1333 return RetVal;\r
1334}\r
1335\r
1336/**\r
1337 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
1338\r
1339 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
1340 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1341 the first found varstore will be as ConfigHdr.\r
1342 @retval TRUE This hii package is the reqeust one.\r
1343 @retval FALSE This hii package is not the reqeust one.\r
1344**/ \r
1345BOOLEAN\r
1346IsThisPackageList (\r
1347 IN HII_DATABASE_RECORD *DataBaseRecord,\r
1348 IN EFI_STRING ConfigHdr\r
1349 )\r
1350{\r
1351 EFI_STATUS Status;\r
1352 UINTN IfrOffset;\r
1353 UINTN PackageOffset;\r
1354 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1355 CHAR16 *VarStoreName;\r
1356 UINT8 *HiiFormPackage;\r
1357 UINTN PackageSize;\r
1358 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
1359 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
1360 EFI_IFR_VARSTORE *IfrVarStore;\r
1361 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
1362 BOOLEAN FindVarstore;\r
1363\r
1364 HiiFormPackage = NULL;\r
1365 VarStoreName = NULL;\r
1366 Status = EFI_SUCCESS;\r
1367 FindVarstore = FALSE;\r
1368\r
1369 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);\r
1370 if (EFI_ERROR (Status)) {\r
1371 return FALSE;\r
1372 }\r
1373\r
1374 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1375 PackageOffset = IfrOffset;\r
1376 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;\r
1377\r
1378 while (IfrOffset < PackageSize) {\r
1379 //\r
1380 // More than one form packages exist.\r
1381 //\r
1382 if (PackageOffset >= PackageHeader->Length) {\r
1383 //\r
1384 // Process the new form package.\r
1385 //\r
1386 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1387 IfrOffset += PackageOffset;\r
1388 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);\r
1389 }\r
1390\r
1391 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);\r
1392 IfrOffset += IfrOpHdr->Length;\r
1393 PackageOffset += IfrOpHdr->Length;\r
1394\r
1395 switch (IfrOpHdr->OpCode) {\r
1396 \r
1397 case EFI_IFR_VARSTORE_OP:\r
1398 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
1399\r
1400 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
1401 if (VarStoreName == NULL) {\r
1402 goto Done;\r
1403 }\r
1404 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);\r
1405\r
1406 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
1407 FindVarstore = TRUE;\r
1408 goto Done;\r
1409 }\r
1410 break;\r
1411\r
1412 case EFI_IFR_VARSTORE_EFI_OP:\r
1413 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1414 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
1415 if (VarStoreName == NULL) {\r
1416 goto Done;\r
1417 }\r
1418 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);\r
1419\r
1420 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
1421 FindVarstore = TRUE;\r
1422 goto Done;\r
1423 }\r
1424 break;\r
1425\r
1426 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1427 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1428\r
1429 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
1430 FindVarstore = TRUE;\r
1431 goto Done;\r
1432 }\r
1433 break;\r
1434 \r
1435 case EFI_IFR_FORM_OP:\r
1436 case EFI_IFR_FORM_MAP_OP:\r
1437 //\r
1438 // No matched varstore is found and directly return.\r
1439 //\r
1440 goto Done;\r
1441\r
1442 default:\r
1443 break;\r
1444 }\r
1445 }\r
1446Done:\r
1447 if (HiiFormPackage != NULL) {\r
1448 FreePool (HiiFormPackage);\r
1449 }\r
1450\r
1451 if (VarStoreName != NULL) {\r
1452 FreePool (VarStoreName);\r
1453 }\r
1454\r
1455 return FindVarstore;\r
1456}\r
1457\r
1458/**\r
1459 Check whether the this op code is required.\r
1460\r
1461 @param RequestBlockArray The array includes all the request info or NULL.\r
1462 @param HiiHandle The hii handle for this form package.\r
1463 @param VarStorageData The varstore data strucure.\r
1464 @param IfrOpHdr Ifr opcode header for this opcode.\r
1465 @param VarWidth The buffer width for this opcode.\r
1466 @param ReturnData The data block added for this opcode.\r
1467\r
1468 @retval EFI_SUCCESS This opcode is required.\r
1469 @retval Others This opcode is not required or error occur.\r
1470 \r
1471**/\r
1472EFI_STATUS\r
1473IsThisOpcodeRequired (\r
1474 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1475 IN EFI_HII_HANDLE HiiHandle,\r
1476 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
1477 IN EFI_IFR_OP_HEADER *IfrOpHdr,\r
1478 IN UINT16 VarWidth,\r
1479 OUT IFR_BLOCK_DATA **ReturnData\r
1480 )\r
1481{\r
1482 IFR_BLOCK_DATA *BlockData;\r
1483 UINT16 VarOffset;\r
1484 EFI_STRING_ID NameId;\r
1485 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
1486\r
1487 NameId = 0;\r
1488 VarOffset = 0;\r
1489 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));\r
1490\r
1491 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1492 NameId = IfrQuestionHdr->VarStoreInfo.VarName;\r
1493\r
1494 //\r
1495 // Check whether this question is in requested block array.\r
1496 //\r
1497 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {\r
1498 //\r
1499 // This question is not in the requested string. Skip it.\r
1500 //\r
1501 return EFI_SUCCESS;\r
1502 }\r
1503 } else {\r
1504 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
1505 \r
1506 //\r
1507 // Check whether this question is in requested block array.\r
1508 //\r
1509 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {\r
1510 //\r
1511 // This question is not in the requested string. Skip it.\r
1512 //\r
1513 return EFI_SUCCESS;\r
1514 }\r
1515\r
1516 //\r
1517 // Check this var question is in the var storage \r
1518 //\r
1519 if (((VarOffset + VarWidth) > VarStorageData->Size)) {\r
1520 return EFI_INVALID_PARAMETER;\r
1521 }\r
1522 }\r
1523\r
1524 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1525 if (BlockData == NULL) {\r
1526 return EFI_OUT_OF_RESOURCES;\r
1527 }\r
1528\r
1529 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1530 BlockData->Name = InternalGetString(HiiHandle, NameId);\r
1531 } else {\r
1532 BlockData->Offset = VarOffset;\r
1533 }\r
1534\r
1535 BlockData->Width = VarWidth;\r
1536 BlockData->QuestionId = IfrQuestionHdr->QuestionId;\r
1537 BlockData->OpCode = IfrOpHdr->OpCode;\r
1538 BlockData->Scope = IfrOpHdr->Scope;\r
1539 InitializeListHead (&BlockData->DefaultValueEntry);\r
1540 //\r
1541 // Add Block Data into VarStorageData BlockEntry\r
1542 //\r
1543 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
1544 *ReturnData = BlockData;\r
1545\r
1546 return EFI_SUCCESS;\r
1547}\r
1548\r
1549/**\r
1550 This function parses Form Package to get the block array and the default\r
1551 value array according to the request ConfigHdr.\r
1552\r
1553 @param HiiHandle Hii Handle for this hii package.\r
1554 @param Package Pointer to the form package data.\r
1555 @param PackageLength Length of the pacakge.\r
1556 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
1557 the first found varstore will be as ConfigHdr.\r
1558 @param RequestBlockArray The block array is retrieved from the request string.\r
1559 @param VarStorageData VarStorage structure contains the got block and default value.\r
1560 @param DefaultIdArray Point to the got default id and default name array.\r
1561\r
1562 @retval EFI_SUCCESS The block array and the default value array are got.\r
1563 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
1564 are conflicted. \r
1565 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
1566**/\r
1567EFI_STATUS\r
1568EFIAPI\r
1569ParseIfrData (\r
1570 IN EFI_HII_HANDLE HiiHandle,\r
1571 IN UINT8 *Package,\r
1572 IN UINT32 PackageLength,\r
1573 IN EFI_STRING ConfigHdr,\r
1574 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1575 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
1576 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
1577 )\r
1578{\r
1579 EFI_STATUS Status;\r
1580 UINTN IfrOffset;\r
1581 UINTN PackageOffset;\r
1582 EFI_IFR_VARSTORE *IfrVarStore;\r
1583 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
1584 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1585 EFI_IFR_ONE_OF *IfrOneOf;\r
1586 EFI_IFR_REF4 *IfrRef;\r
1587 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
1588 EFI_IFR_DEFAULT *IfrDefault;\r
1589 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
1590 EFI_IFR_CHECKBOX *IfrCheckBox;\r
1591 EFI_IFR_PASSWORD *IfrPassword;\r
1592 EFI_IFR_STRING *IfrString;\r
1593 EFI_IFR_DATE *IfrDate;\r
1594 EFI_IFR_TIME *IfrTime;\r
1595 IFR_DEFAULT_DATA DefaultData;\r
1596 IFR_DEFAULT_DATA *DefaultDataPtr;\r
1597 IFR_BLOCK_DATA *BlockData;\r
1598 CHAR16 *VarStoreName;\r
1599 UINT16 VarWidth;\r
1600 UINT16 VarDefaultId;\r
1601 BOOLEAN FirstOneOfOption;\r
1602 LIST_ENTRY *LinkData;\r
1603 LIST_ENTRY *LinkDefault;\r
1604 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
1605 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
1606 EFI_VARSTORE_ID VarStoreId;\r
1607\r
1608 Status = EFI_SUCCESS;\r
1609 BlockData = NULL;\r
1610 DefaultDataPtr = NULL;\r
1611 FirstOneOfOption = FALSE;\r
1612 VarStoreId = 0;\r
1613 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
1614\r
1615 //\r
1616 // Go through the form package to parse OpCode one by one.\r
1617 //\r
1618 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1619 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;\r
1620 IfrOffset = PackageOffset;\r
1621 while (IfrOffset < PackageLength) {\r
1622\r
1623 //\r
1624 // More than one form package found.\r
1625 //\r
1626 if (PackageOffset >= PackageHeader->Length) {\r
1627 //\r
1628 // Already found varstore for this request, break;\r
1629 //\r
1630 if (VarStoreId != 0) {\r
1631 VarStoreId = 0;\r
1632 }\r
1633\r
1634 //\r
1635 // Get next package header info.\r
1636 //\r
1637 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);\r
1638 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
1639 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);\r
1640 }\r
1641\r
1642 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
1643 switch (IfrOpHdr->OpCode) {\r
1644 case EFI_IFR_VARSTORE_OP:\r
1645 //\r
1646 // VarStore is found. Don't need to search any more.\r
1647 //\r
1648 if (VarStoreId != 0) {\r
1649 break;\r
1650 }\r
1651\r
1652 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
1653\r
1654 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
1655 if (VarStoreName == NULL) {\r
1656 Status = EFI_OUT_OF_RESOURCES;\r
1657 goto Done;\r
1658 }\r
1659 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);\r
1660\r
1661 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
1662 //\r
1663 // Find the matched VarStore\r
1664 //\r
1665 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
1666 VarStorageData->Size = IfrVarStore->Size;\r
1667 VarStorageData->Name = VarStoreName;\r
1668 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
1669 VarStoreId = IfrVarStore->VarStoreId;\r
1670 }\r
1671 break;\r
1672\r
1673 case EFI_IFR_VARSTORE_EFI_OP:\r
1674 //\r
1675 // VarStore is found. Don't need to search any more.\r
1676 //\r
1677 if (VarStoreId != 0) {\r
1678 break;\r
1679 }\r
1680\r
1681 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1682\r
1683 //\r
1684 // If the length is small than the structure, this is from old efi \r
1685 // varstore definition. Old efi varstore get config directly from \r
1686 // GetVariable function.\r
1687 // \r
1688 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
1689 break;\r
1690 }\r
1691\r
1692 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
1693 if (VarStoreName == NULL) {\r
1694 Status = EFI_OUT_OF_RESOURCES;\r
1695 goto Done;\r
1696 }\r
1697 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);\r
1698\r
1699 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
1700 //\r
1701 // Find the matched VarStore\r
1702 //\r
1703 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
1704 VarStorageData->Size = IfrEfiVarStore->Size;\r
1705 VarStorageData->Name = VarStoreName;\r
1706 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
1707 VarStoreId = IfrEfiVarStore->VarStoreId;\r
1708 }\r
1709 break;\r
1710\r
1711 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1712 //\r
1713 // VarStore is found. Don't need to search any more.\r
1714 //\r
1715 if (VarStoreId != 0) {\r
1716 break;\r
1717 }\r
1718\r
1719 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1720\r
1721 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
1722 //\r
1723 // Find the matched VarStore\r
1724 //\r
1725 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);\r
1726 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
1727 VarStoreId = IfrNameValueVarStore->VarStoreId;\r
1728 }\r
1729 break;\r
1730\r
1731 case EFI_IFR_DEFAULTSTORE_OP:\r
1732 //\r
1733 // Add new the map between default id and default name.\r
1734 //\r
1735 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
1736 if (DefaultDataPtr == NULL) {\r
1737 Status = EFI_OUT_OF_RESOURCES;\r
1738 goto Done;\r
1739 }\r
1740 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
1741 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
1742 DefaultDataPtr = NULL;\r
1743 break;\r
1744\r
1745 case EFI_IFR_FORM_OP:\r
1746 case EFI_IFR_FORM_MAP_OP:\r
1747 //\r
1748 // No matched varstore is found and directly return.\r
1749 //\r
1750 if ( VarStoreId == 0) {\r
1751 Status = EFI_SUCCESS;\r
1752 goto Done;\r
1753 }\r
1754 break;\r
1755\r
1756 case EFI_IFR_REF_OP:\r
1757 //\r
1758 // Ref question is not in IFR Form. This IFR form is not valid. \r
1759 //\r
1760 if ( VarStoreId == 0) {\r
1761 Status = EFI_INVALID_PARAMETER;\r
1762 goto Done;\r
1763 }\r
1764 //\r
1765 // Check whether this question is for the requested varstore.\r
1766 //\r
1767 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
1768 if (IfrRef->Question.VarStoreId != VarStoreId) {\r
1769 break;\r
1770 }\r
1771 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
1772\r
1773 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1774 if (EFI_ERROR (Status)) {\r
1775 goto Done;\r
1776 }\r
1777 break;\r
1778\r
1779 case EFI_IFR_ONE_OF_OP:\r
1780 case EFI_IFR_NUMERIC_OP:\r
1781 //\r
1782 // Numeric and OneOf has the same opcode structure.\r
1783 //\r
1784\r
1785 //\r
1786 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
1787 //\r
1788 if (VarStoreId == 0) {\r
1789 Status = EFI_INVALID_PARAMETER;\r
1790 goto Done;\r
1791 }\r
1792 //\r
1793 // Check whether this question is for the requested varstore.\r
1794 //\r
1795 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1796 if (IfrOneOf->Question.VarStoreId != VarStoreId) {\r
1797 break;\r
1798 }\r
1799 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
1800\r
1801 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1802 if (EFI_ERROR (Status)) {\r
1803 goto Done;\r
1804 }\r
1805\r
1806 if (BlockData == NULL) {\r
1807 //\r
1808 // BlockData == NULL means this opcode is not in the requst array.\r
1809 //\r
1810 break;\r
1811 }\r
1812\r
1813 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
1814 //\r
1815 // Set this flag to TRUE for the first oneof option.\r
1816 //\r
1817 FirstOneOfOption = TRUE;\r
1818 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
1819 //\r
1820 // Numeric minimum value will be used as default value when no default is specified. \r
1821 //\r
1822 DefaultData.Type = DefaultValueFromDefault;\r
1823 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1824 case EFI_IFR_NUMERIC_SIZE_1:\r
1825 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
1826 break;\r
1827\r
1828 case EFI_IFR_NUMERIC_SIZE_2:\r
1829 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
1830 break;\r
1831\r
1832 case EFI_IFR_NUMERIC_SIZE_4:\r
1833 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
1834 break;\r
1835\r
1836 case EFI_IFR_NUMERIC_SIZE_8:\r
1837 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
1838 break;\r
1839\r
1840 default:\r
1841 Status = EFI_INVALID_PARAMETER;\r
1842 goto Done;\r
1843 }\r
1844 //\r
1845 // Set default value base on the DefaultId list get from IFR data.\r
1846 // \r
1847 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
1848 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
1849 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
1850 InsertDefaultValue (BlockData, &DefaultData);\r
1851 }\r
1852 }\r
1853 break;\r
1854\r
1855 case EFI_IFR_ORDERED_LIST_OP:\r
1856 //\r
1857 // offset by question header\r
1858 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
1859 // no default value and default id, how to define its default value?\r
1860 //\r
1861\r
1862 //\r
1863 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
1864 //\r
1865 if (VarStoreId == 0) {\r
1866 Status = EFI_INVALID_PARAMETER;\r
1867 goto Done;\r
1868 }\r
1869 //\r
1870 // Check whether this question is for the requested varstore.\r
1871 //\r
1872 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
1873 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {\r
1874 BlockData = NULL;\r
1875 break;\r
1876 }\r
1877 VarWidth = IfrOrderedList->MaxContainers;\r
1878 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1879 if (EFI_ERROR (Status)) {\r
1880 goto Done;\r
1881 }\r
1882 break;\r
1883\r
1884 case EFI_IFR_CHECKBOX_OP:\r
1885 //\r
1886 // EFI_IFR_DEFAULT_OP\r
1887 // offset by question header\r
1888 // width is 1 sizeof (BOOLEAN)\r
1889 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
1890 // value by DefaultOption\r
1891 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
1892 // \r
1893\r
1894 //\r
1895 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1896 //\r
1897 if (VarStoreId == 0) {\r
1898 Status = EFI_INVALID_PARAMETER;\r
1899 goto Done;\r
1900 }\r
1901 //\r
1902 // Check whether this question is for the requested varstore.\r
1903 //\r
1904 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1905 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {\r
1906 break;\r
1907 }\r
1908 VarWidth = (UINT16) sizeof (BOOLEAN);\r
1909 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1910 if (EFI_ERROR (Status)) {\r
1911 goto Done;\r
1912 }\r
1913\r
1914 if (BlockData == NULL) {\r
1915 //\r
1916 // BlockData == NULL means this opcode is not in the requst array.\r
1917 //\r
1918 break;\r
1919 }\r
1920\r
1921 //\r
1922 // Add default value for standard ID by CheckBox Flag\r
1923 //\r
1924 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
1925 //\r
1926 // Prepare new DefaultValue\r
1927 //\r
1928 DefaultData.DefaultId = VarDefaultId;\r
1929 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
1930 //\r
1931 // When flag is set, defautl value is TRUE.\r
1932 //\r
1933 DefaultData.Type = DefaultValueFromFlag;\r
1934 DefaultData.Value.b = TRUE;\r
1935 } else {\r
1936 //\r
1937 // When flag is not set, defautl value is FASLE.\r
1938 //\r
1939 DefaultData.Type = DefaultValueFromDefault;\r
1940 DefaultData.Value.b = FALSE;\r
1941 }\r
1942 //\r
1943 // Add DefaultValue into current BlockData\r
1944 //\r
1945 InsertDefaultValue (BlockData, &DefaultData);\r
1946\r
1947 //\r
1948 // Add default value for Manufacture ID by CheckBox Flag\r
1949 //\r
1950 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
1951 //\r
1952 // Prepare new DefaultValue\r
1953 //\r
1954 DefaultData.DefaultId = VarDefaultId;\r
1955 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
1956 //\r
1957 // When flag is set, defautl value is TRUE.\r
1958 //\r
1959 DefaultData.Type = DefaultValueFromFlag;\r
1960 DefaultData.Value.b = TRUE;\r
1961 } else {\r
1962 //\r
1963 // When flag is not set, defautl value is FASLE.\r
1964 //\r
1965 DefaultData.Type = DefaultValueFromDefault;\r
1966 DefaultData.Value.b = FALSE;\r
1967 }\r
1968 //\r
1969 // Add DefaultValue into current BlockData\r
1970 //\r
1971 InsertDefaultValue (BlockData, &DefaultData);\r
1972 break;\r
1973\r
1974 case EFI_IFR_DATE_OP:\r
1975 //\r
1976 // offset by question header\r
1977 // width MaxSize * sizeof (CHAR16)\r
1978 // no default value, only block array\r
1979 //\r
1980\r
1981 //\r
1982 // Date question is not in IFR Form. This IFR form is not valid. \r
1983 //\r
1984 if (VarStoreId == 0) {\r
1985 Status = EFI_INVALID_PARAMETER;\r
1986 goto Done;\r
1987 }\r
1988 //\r
1989 // Check whether this question is for the requested varstore.\r
1990 //\r
1991 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
1992 if (IfrDate->Question.VarStoreId != VarStoreId) {\r
1993 break;\r
1994 }\r
1995\r
1996 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
1997 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
1998 if (EFI_ERROR (Status)) {\r
1999 goto Done;\r
2000 }\r
2001 break;\r
2002\r
2003 case EFI_IFR_TIME_OP:\r
2004 //\r
2005 // offset by question header\r
2006 // width MaxSize * sizeof (CHAR16)\r
2007 // no default value, only block array\r
2008 //\r
2009\r
2010 //\r
2011 // Time question is not in IFR Form. This IFR form is not valid. \r
2012 //\r
2013 if (VarStoreId == 0) {\r
2014 Status = EFI_INVALID_PARAMETER;\r
2015 goto Done;\r
2016 }\r
2017 //\r
2018 // Check whether this question is for the requested varstore.\r
2019 //\r
2020 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
2021 if (IfrTime->Question.VarStoreId != VarStoreId) {\r
2022 break;\r
2023 }\r
2024\r
2025 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
2026 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2027 if (EFI_ERROR (Status)) {\r
2028 goto Done;\r
2029 }\r
2030 break;\r
2031\r
2032 case EFI_IFR_STRING_OP:\r
2033 //\r
2034 // offset by question header\r
2035 // width MaxSize * sizeof (CHAR16)\r
2036 // no default value, only block array\r
2037 //\r
2038\r
2039 //\r
2040 // String question is not in IFR Form. This IFR form is not valid. \r
2041 //\r
2042 if (VarStoreId == 0) {\r
2043 Status = EFI_INVALID_PARAMETER;\r
2044 goto Done;\r
2045 }\r
2046 //\r
2047 // Check whether this question is for the requested varstore.\r
2048 //\r
2049 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
2050 if (IfrString->Question.VarStoreId != VarStoreId) {\r
2051 break;\r
2052 }\r
2053\r
2054 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
2055 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2056 if (EFI_ERROR (Status)) {\r
2057 goto Done;\r
2058 }\r
2059\r
2060 //\r
2061 // No default value for string.\r
2062 //\r
2063 BlockData = NULL;\r
2064 break;\r
2065\r
2066 case EFI_IFR_PASSWORD_OP:\r
2067 //\r
2068 // offset by question header\r
2069 // width MaxSize * sizeof (CHAR16)\r
2070 // no default value, only block array\r
2071 //\r
2072\r
2073 //\r
2074 // Password question is not in IFR Form. This IFR form is not valid. \r
2075 //\r
2076 if (VarStoreId == 0) {\r
2077 Status = EFI_INVALID_PARAMETER;\r
2078 goto Done;\r
2079 }\r
2080 //\r
2081 // Check whether this question is for the requested varstore.\r
2082 //\r
2083 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
2084 if (IfrPassword->Question.VarStoreId != VarStoreId) {\r
2085 break;\r
2086 }\r
2087\r
2088 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
2089 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);\r
2090 if (EFI_ERROR (Status)) {\r
2091 goto Done;\r
2092 }\r
2093\r
2094 //\r
2095 // No default value for string.\r
2096 //\r
2097 BlockData = NULL;\r
2098 break;\r
2099\r
2100 case EFI_IFR_ONE_OF_OPTION_OP:\r
2101 //\r
2102 // No matched block data is ignored.\r
2103 //\r
2104 if (BlockData == NULL || BlockData->Scope == 0) {\r
2105 break;\r
2106 }\r
2107\r
2108 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
2109 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2110 //\r
2111 // Get ordered list option data type.\r
2112 //\r
2113 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
2114 VarWidth = 1;\r
2115 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
2116 VarWidth = 2;\r
2117 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
2118 VarWidth = 4;\r
2119 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
2120 VarWidth = 8;\r
2121 } else {\r
2122 //\r
2123 // Invalid ordered list option data type.\r
2124 //\r
2125 Status = EFI_INVALID_PARAMETER;\r
2126 if (BlockData->Name != NULL) {\r
2127 FreePool (BlockData->Name);\r
2128 }\r
2129 FreePool (BlockData);\r
2130 goto Done;\r
2131 }\r
2132\r
2133 //\r
2134 // Calculate Ordered list QuestionId width.\r
2135 //\r
2136 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
2137 //\r
2138 // Check whether this question is in requested block array.\r
2139 //\r
2140 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
2141 //\r
2142 // This question is not in the requested string. Skip it.\r
2143 //\r
2144 if (BlockData->Name != NULL) {\r
2145 FreePool (BlockData->Name);\r
2146 }\r
2147 FreePool (BlockData);\r
2148 BlockData = NULL;\r
2149 break;\r
2150 }\r
2151 //\r
2152 // Check this var question is in the var storage \r
2153 //\r
2154 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
2155 Status = EFI_INVALID_PARAMETER;\r
2156 if (BlockData->Name != NULL) {\r
2157 FreePool (BlockData->Name);\r
2158 }\r
2159 FreePool (BlockData);\r
2160 goto Done;\r
2161 }\r
2162 //\r
2163 // Add Block Data into VarStorageData BlockEntry\r
2164 //\r
2165 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
2166 //\r
2167 // No default data for OrderedList.\r
2168 //\r
2169 BlockData = NULL;\r
2170 break;\r
2171 }\r
2172\r
2173 //\r
2174 // 1. Set default value for OneOf option when flag field has default attribute.\r
2175 //\r
2176 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
2177 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
2178 //\r
2179 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2180 // The first oneof option value will be used as default value when no default value is specified. \r
2181 //\r
2182 FirstOneOfOption = FALSE;\r
2183 \r
2184 // Prepare new DefaultValue\r
2185 //\r
2186 DefaultData.Type = DefaultValueFromFlag;\r
2187 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
2188 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
2189 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2190 InsertDefaultValue (BlockData, &DefaultData);\r
2191 } \r
2192 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
2193 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2194 InsertDefaultValue (BlockData, &DefaultData);\r
2195 }\r
2196 }\r
2197\r
2198 //\r
2199 // 2. Set as the default value when this is the first option.\r
2200 // The first oneof option value will be used as default value when no default value is specified. \r
2201 //\r
2202 if (FirstOneOfOption) {\r
2203 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2204 FirstOneOfOption = FALSE;\r
2205 \r
2206 //\r
2207 // Prepare new DefaultValue\r
2208 // \r
2209 DefaultData.Type = DefaultValueFromDefault;\r
2210 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
2211 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2212 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
2213 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2214 InsertDefaultValue (BlockData, &DefaultData);\r
2215 }\r
2216 }\r
2217 break;\r
2218\r
2219 case EFI_IFR_DEFAULT_OP:\r
2220 //\r
2221 // Update Current BlockData to the default value.\r
2222 //\r
2223 if (BlockData == NULL || BlockData->Scope == 0) {\r
2224 //\r
2225 // No matched block data is ignored.\r
2226 //\r
2227 break;\r
2228 }\r
2229\r
2230 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
2231 //\r
2232 // OrderedList Opcode is no default value.\r
2233 //\r
2234 break;\r
2235 }\r
2236 //\r
2237 // Get the DefaultId\r
2238 //\r
2239 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
2240 VarDefaultId = IfrDefault->DefaultId;\r
2241 //\r
2242 // Prepare new DefaultValue\r
2243 //\r
2244 DefaultData.Type = DefaultValueFromOpcode;\r
2245 DefaultData.DefaultId = VarDefaultId;\r
2246 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
2247\r
2248 // If the value field is expression, set the cleaned flag.\r
2249 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
2250 DefaultData.Cleaned = TRUE;\r
2251 }\r
2252 //\r
2253 // Add DefaultValue into current BlockData\r
2254 //\r
2255 InsertDefaultValue (BlockData, &DefaultData);\r
2256\r
2257 //\r
2258 // After insert the default value, reset the cleaned value for next \r
2259 // time used. If not set here, need to set the value before everytime \r
2260 // use it.\r
2261 //\r
2262 DefaultData.Cleaned = FALSE;\r
2263 break;\r
2264\r
2265 case EFI_IFR_END_OP:\r
2266 //\r
2267 // End Opcode is for Var question.\r
2268 //\r
2269 if (BlockData != NULL) {\r
2270 if (BlockData->Scope > 0) {\r
2271 BlockData->Scope--;\r
2272 }\r
2273 if (BlockData->Scope == 0) {\r
2274 BlockData = NULL;\r
2275 }\r
2276 }\r
2277\r
2278 break;\r
2279\r
2280 default:\r
2281 if (BlockData != NULL) {\r
2282 if (BlockData->Scope > 0) {\r
2283 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
2284 }\r
2285\r
2286 if (BlockData->Scope == 0) {\r
2287 BlockData = NULL;\r
2288 }\r
2289 }\r
2290 break;\r
2291 }\r
2292\r
2293 IfrOffset += IfrOpHdr->Length;\r
2294 PackageOffset += IfrOpHdr->Length;\r
2295 }\r
2296\r
2297Done:\r
2298 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2299 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2300 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
2301 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2302 LinkDefault = LinkDefault->ForwardLink;\r
2303 if (DefaultDataPtr->Cleaned == TRUE) {\r
2304 RemoveEntryList (&DefaultDataPtr->Entry);\r
2305 FreePool (DefaultDataPtr);\r
2306 }\r
2307 }\r
2308 }\r
2309\r
2310 return Status;\r
2311}\r
2312\r
2313/**\r
2314 parse the configrequest string, get the elements.\r
2315\r
2316 @param ConfigRequest The input configrequest string.\r
2317 @param Progress Return the progress data.\r
2318\r
2319 @retval Block data pointer.\r
2320**/\r
2321IFR_BLOCK_DATA *\r
2322GetBlockElement (\r
2323 IN EFI_STRING ConfigRequest,\r
2324 OUT EFI_STRING *Progress\r
2325 )\r
2326{\r
2327 EFI_STRING StringPtr;\r
2328 IFR_BLOCK_DATA *BlockData;\r
2329 IFR_BLOCK_DATA *RequestBlockArray;\r
2330 EFI_STATUS Status;\r
2331 UINT8 *TmpBuffer;\r
2332 UINT16 Offset;\r
2333 UINT16 Width;\r
2334 LIST_ENTRY *Link;\r
2335 IFR_BLOCK_DATA *NextBlockData;\r
2336 UINTN Length;\r
2337\r
2338 TmpBuffer = NULL;\r
2339\r
2340 //\r
2341 // Init RequestBlockArray\r
2342 //\r
2343 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2344 if (RequestBlockArray == NULL) {\r
2345 goto Done;\r
2346 }\r
2347 InitializeListHead (&RequestBlockArray->Entry);\r
2348\r
2349 //\r
2350 // Get the request Block array from the request string\r
2351 // Offset and Width\r
2352 //\r
2353\r
2354 //\r
2355 // Parse each <RequestElement> if exists\r
2356 // Only <BlockName> format is supported by this help function.\r
2357 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
2358 //\r
2359 StringPtr = ConfigRequest;\r
2360 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
2361 //\r
2362 // Skip the OFFSET string\r
2363 //\r
2364 *Progress = StringPtr;\r
2365 StringPtr += StrLen (L"&OFFSET=");\r
2366 //\r
2367 // Get Offset\r
2368 //\r
2369 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2370 if (EFI_ERROR (Status)) {\r
2371 goto Done;\r
2372 }\r
2373 Offset = 0;\r
2374 CopyMem (\r
2375 &Offset,\r
2376 TmpBuffer,\r
2377 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2378 );\r
2379 FreePool (TmpBuffer);\r
2380\r
2381 StringPtr += Length;\r
2382 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
2383 goto Done;\r
2384 }\r
2385 StringPtr += StrLen (L"&WIDTH=");\r
2386\r
2387 //\r
2388 // Get Width\r
2389 //\r
2390 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2391 if (EFI_ERROR (Status)) {\r
2392 goto Done;\r
2393 }\r
2394 Width = 0;\r
2395 CopyMem (\r
2396 &Width,\r
2397 TmpBuffer,\r
2398 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
2399 );\r
2400 FreePool (TmpBuffer);\r
2401\r
2402 StringPtr += Length;\r
2403 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2404 goto Done;\r
2405 }\r
2406 \r
2407 //\r
2408 // Set Block Data\r
2409 //\r
2410 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2411 if (BlockData == NULL) {\r
2412 goto Done;\r
2413 }\r
2414 BlockData->Offset = Offset;\r
2415 BlockData->Width = Width;\r
2416 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2417\r
2418 //\r
2419 // Skip &VALUE string if &VALUE does exists.\r
2420 //\r
2421 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
2422 StringPtr += StrLen (L"&VALUE=");\r
2423\r
2424 //\r
2425 // Get Value\r
2426 //\r
2427 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
2428 if (EFI_ERROR (Status)) {\r
2429 goto Done;\r
2430 }\r
2431\r
2432 StringPtr += Length;\r
2433 if (*StringPtr != 0 && *StringPtr != L'&') {\r
2434 goto Done;\r
2435 }\r
2436 }\r
2437 //\r
2438 // If '\0', parsing is finished. \r
2439 //\r
2440 if (*StringPtr == 0) {\r
2441 break;\r
2442 }\r
2443 }\r
2444\r
2445 //\r
2446 // Merge the requested block data.\r
2447 //\r
2448 Link = RequestBlockArray->Entry.ForwardLink;\r
2449 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
2450 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2451 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
2452 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
2453 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
2454 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
2455 }\r
2456 RemoveEntryList (Link->ForwardLink);\r
2457 FreePool (NextBlockData);\r
2458 continue;\r
2459 }\r
2460 Link = Link->ForwardLink;\r
2461 }\r
2462\r
2463 return RequestBlockArray;\r
2464\r
2465Done:\r
2466 if (RequestBlockArray != NULL) {\r
2467 //\r
2468 // Free Link Array RequestBlockArray\r
2469 //\r
2470 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2471 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2472 RemoveEntryList (&BlockData->Entry);\r
2473 FreePool (BlockData);\r
2474 }\r
2475\r
2476 FreePool (RequestBlockArray);\r
2477 }\r
2478\r
2479 return NULL;\r
2480}\r
2481\r
2482/**\r
2483 parse the configrequest string, get the elements.\r
2484\r
2485 @param ConfigRequest The input config request string.\r
2486 @param Progress Return the progress data.\r
2487\r
2488 @retval return data block array.\r
2489**/\r
2490IFR_BLOCK_DATA *\r
2491GetNameElement (\r
2492 IN EFI_STRING ConfigRequest,\r
2493 OUT EFI_STRING *Progress\r
2494 )\r
2495{\r
2496 EFI_STRING StringPtr;\r
2497 EFI_STRING NextTag;\r
2498 IFR_BLOCK_DATA *BlockData;\r
2499 IFR_BLOCK_DATA *RequestBlockArray;\r
2500 BOOLEAN HasValue;\r
2501\r
2502 StringPtr = ConfigRequest;\r
2503\r
2504 //\r
2505 // Init RequestBlockArray\r
2506 //\r
2507 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2508 if (RequestBlockArray == NULL) {\r
2509 goto Done;\r
2510 }\r
2511 InitializeListHead (&RequestBlockArray->Entry);\r
2512\r
2513 //\r
2514 // Get the request Block array from the request string\r
2515 //\r
2516\r
2517 //\r
2518 // Parse each <RequestElement> if exists\r
2519 // Only <BlockName> format is supported by this help function.\r
2520 // <BlockName> ::= &'Name***=***\r
2521 //\r
2522 while (StringPtr != NULL && *StringPtr == L'&') {\r
2523\r
2524 *Progress = StringPtr;\r
2525 //\r
2526 // Skip the L"&" string\r
2527 //\r
2528 StringPtr += 1;\r
2529\r
2530 HasValue = FALSE;\r
2531 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
2532 *NextTag = L'\0';\r
2533 HasValue = TRUE;\r
2534 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
2535 *NextTag = L'\0';\r
2536 }\r
2537\r
2538 //\r
2539 // Set Block Data\r
2540 //\r
2541 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2542 if (BlockData == NULL) {\r
2543 goto Done;\r
2544 }\r
2545\r
2546 //\r
2547 // Get Name\r
2548 //\r
2549 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
2550 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
2551\r
2552 if (HasValue) {\r
2553 //\r
2554 // If has value, skip the value.\r
2555 // \r
2556 StringPtr = NextTag + 1;\r
2557 *NextTag = L'=';\r
2558 StringPtr = StrStr (StringPtr, L"&");\r
2559 } else if (NextTag != NULL) {\r
2560 //\r
2561 // restore the '&' text.\r
2562 //\r
2563 StringPtr = NextTag;\r
2564 *NextTag = L'&';\r
2565 }\r
2566 }\r
2567\r
2568 return RequestBlockArray;\r
2569\r
2570Done:\r
2571 if (RequestBlockArray != NULL) {\r
2572 //\r
2573 // Free Link Array RequestBlockArray\r
2574 //\r
2575 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
2576 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2577 RemoveEntryList (&BlockData->Entry);\r
2578 if (BlockData->Name != NULL) {\r
2579 FreePool (BlockData->Name);\r
2580 }\r
2581 FreePool (BlockData);\r
2582 }\r
2583\r
2584 FreePool (RequestBlockArray);\r
2585 }\r
2586\r
2587 return NULL;\r
2588}\r
2589\r
2590/**\r
2591 Generate ConfigRequest string base on the varstore info.\r
2592\r
2593 @param ConfigHdr The config header for this varstore.\r
2594 @param VarStorageData The varstore info.\r
2595 @param Status Return Status.\r
2596 @param ConfigRequest The ConfigRequest info may be return.\r
2597\r
2598 @retval TRUE Need to continue\r
2599 @retval Others NO need to continue or error occur.\r
2600**/\r
2601BOOLEAN\r
2602GenerateConfigRequest (\r
2603 IN CHAR16 *ConfigHdr,\r
2604 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2605 OUT EFI_STATUS *Status,\r
2606 IN OUT EFI_STRING *ConfigRequest\r
2607 )\r
2608{\r
2609 BOOLEAN DataExist;\r
2610 UINTN Length;\r
2611 LIST_ENTRY *Link;\r
2612 CHAR16 *FullConfigRequest;\r
2613 CHAR16 *StringPtr;\r
2614 IFR_BLOCK_DATA *BlockData;\r
2615\r
2616 //\r
2617 // Append VarStorageData BlockEntry into *Request string\r
2618 // Now support only one varstore in a form package.\r
2619 //\r
2620 \r
2621 //\r
2622 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
2623 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
2624 //\r
2625 \r
2626 //\r
2627 // Compute the length of the entire request starting with <ConfigHdr> and a \r
2628 // Null-terminator\r
2629 //\r
2630 DataExist = FALSE;\r
2631 Length = StrLen (ConfigHdr) + 1;\r
2632\r
2633 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2634 DataExist = TRUE;\r
2635 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2636 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2637 //\r
2638 // Add <BlockName> length for each Name\r
2639 //\r
2640 // <BlockName> ::= &Name1&Name2&... \r
2641 // |1| StrLen(Name1)\r
2642 //\r
2643 Length = Length + (1 + StrLen (BlockData->Name));\r
2644 } else {\r
2645 //\r
2646 // Add <BlockName> length for each Offset/Width pair\r
2647 //\r
2648 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
2649 // | 8 | 4 | 7 | 4 |\r
2650 //\r
2651 Length = Length + (8 + 4 + 7 + 4);\r
2652 }\r
2653 }\r
2654 //\r
2655 // No any request block data is found. The request string can't be constructed.\r
2656 //\r
2657 if (!DataExist) {\r
2658 *Status = EFI_SUCCESS;\r
2659 return FALSE;\r
2660 }\r
2661\r
2662 //\r
2663 // Allocate buffer for the entire <ConfigRequest>\r
2664 //\r
2665 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
2666 if (FullConfigRequest == NULL) {\r
2667 *Status = EFI_OUT_OF_RESOURCES;\r
2668 return FALSE;\r
2669 }\r
2670 StringPtr = FullConfigRequest;\r
2671\r
2672 //\r
2673 // Start with <ConfigHdr>\r
2674 //\r
2675 StrCpyS (StringPtr, Length, ConfigHdr);\r
2676 StringPtr += StrLen (StringPtr);\r
2677\r
2678 //\r
2679 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
2680 //\r
2681 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
2682 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
2683 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2684 //\r
2685 // Append &Name1\0\r
2686 //\r
2687 UnicodeSPrint (\r
2688 StringPtr,\r
2689 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
2690 L"&%s",\r
2691 BlockData->Name\r
2692 );\r
2693 } else {\r
2694 //\r
2695 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
2696 //\r
2697 UnicodeSPrint (\r
2698 StringPtr, \r
2699 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
2700 L"&OFFSET=%04X&WIDTH=%04X", \r
2701 BlockData->Offset, \r
2702 BlockData->Width\r
2703 );\r
2704 }\r
2705 StringPtr += StrLen (StringPtr);\r
2706 }\r
2707 //\r
2708 // Set to the got full request string.\r
2709 //\r
2710 HiiToLower (FullConfigRequest);\r
2711\r
2712 if (*ConfigRequest != NULL) {\r
2713 FreePool (*ConfigRequest);\r
2714 }\r
2715 *ConfigRequest = FullConfigRequest;\r
2716\r
2717 return TRUE;\r
2718}\r
2719\r
2720/**\r
2721 Generate ConfigRequest Header base on the varstore info.\r
2722\r
2723 @param VarStorageData The varstore info.\r
2724 @param DevicePath Device path for this varstore.\r
2725 @param ConfigHdr The config header for this varstore.\r
2726\r
2727 @retval EFI_SUCCESS Generate the header success.\r
2728 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
2729**/\r
2730EFI_STATUS\r
2731GenerateHdr (\r
2732 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2733 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2734 OUT EFI_STRING *ConfigHdr\r
2735 )\r
2736{\r
2737 EFI_STRING GuidStr;\r
2738 EFI_STRING NameStr;\r
2739 EFI_STRING PathStr;\r
2740 UINTN Length;\r
2741 EFI_STATUS Status;\r
2742\r
2743 Status = EFI_SUCCESS;\r
2744 NameStr = NULL;\r
2745 GuidStr = NULL;\r
2746 PathStr = NULL;\r
2747\r
2748 //\r
2749 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
2750 //\r
2751 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
2752 if (VarStorageData->Name != NULL) {\r
2753 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
2754 } else {\r
2755 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
2756 }\r
2757 GenerateSubStr (\r
2758 L"PATH=",\r
2759 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2760 (VOID *) DevicePath,\r
2761 1,\r
2762 &PathStr\r
2763 );\r
2764 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
2765 if (VarStorageData->Name == NULL) {\r
2766 Length += 1;\r
2767 }\r
2768\r
2769 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
2770 if (*ConfigHdr == NULL) {\r
2771 Status = EFI_OUT_OF_RESOURCES;\r
2772 goto Done;\r
2773 }\r
2774 StrCpyS (*ConfigHdr, Length, GuidStr);\r
2775 StrCatS (*ConfigHdr, Length, NameStr);\r
2776 if (VarStorageData->Name == NULL) {\r
2777 StrCatS (*ConfigHdr, Length, L"&");\r
2778 }\r
2779 StrCatS (*ConfigHdr, Length, PathStr);\r
2780\r
2781 //\r
2782 // Remove the last character L'&'\r
2783 //\r
2784 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
2785\r
2786Done:\r
2787 if (GuidStr != NULL) {\r
2788 FreePool (GuidStr);\r
2789 }\r
2790\r
2791 if (NameStr != NULL) {\r
2792 FreePool (NameStr);\r
2793 }\r
2794\r
2795 if (PathStr != NULL) {\r
2796 FreePool (PathStr);\r
2797 }\r
2798\r
2799 return Status;\r
2800}\r
2801\r
2802/**\r
2803 Get Data buffer size based on data type.\r
2804\r
2805 @param ValueType The input data type.\r
2806\r
2807 @retval The data buffer size for the input type.\r
2808**/\r
2809UINT16\r
2810GetStorageWidth (\r
2811 IN UINT8 ValueType\r
2812 )\r
2813{\r
2814 UINT16 StorageWidth;\r
2815\r
2816 switch (ValueType) {\r
2817 case EFI_IFR_NUMERIC_SIZE_1:\r
2818 case EFI_IFR_TYPE_BOOLEAN:\r
2819 StorageWidth = (UINT16) sizeof (UINT8);\r
2820 break;\r
2821\r
2822 case EFI_IFR_NUMERIC_SIZE_2:\r
2823 StorageWidth = (UINT16) sizeof (UINT16);\r
2824 break;\r
2825\r
2826 case EFI_IFR_NUMERIC_SIZE_4:\r
2827 StorageWidth = (UINT16) sizeof (UINT32);\r
2828 break;\r
2829\r
2830 case EFI_IFR_NUMERIC_SIZE_8:\r
2831 StorageWidth = (UINT16) sizeof (UINT64);\r
2832 break;\r
2833\r
2834 case EFI_IFR_TYPE_TIME:\r
2835 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
2836 break;\r
2837\r
2838 case EFI_IFR_TYPE_DATE:\r
2839 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
2840 break;\r
2841\r
2842 default:\r
2843 StorageWidth = 0;\r
2844 break;\r
2845 }\r
2846\r
2847 return StorageWidth;\r
2848}\r
2849\r
2850/**\r
2851 Generate ConfigAltResp string base on the varstore info.\r
2852\r
2853 @param ConfigHdr The config header for this varstore.\r
2854 @param VarStorageData The varstore info.\r
2855 @param DefaultIdArray The Default id array.\r
2856 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
2857\r
2858 @retval TRUE Need to continue\r
2859 @retval Others NO need to continue or error occur.\r
2860**/\r
2861EFI_STATUS\r
2862GenerateAltConfigResp (\r
2863 IN CHAR16 *ConfigHdr,\r
2864 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
2865 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
2866 IN OUT EFI_STRING *DefaultAltCfgResp\r
2867 )\r
2868{\r
2869 BOOLEAN DataExist;\r
2870 UINTN Length;\r
2871 LIST_ENTRY *Link;\r
2872 LIST_ENTRY *LinkData;\r
2873 LIST_ENTRY *LinkDefault;\r
2874 LIST_ENTRY *ListEntry;\r
2875 CHAR16 *StringPtr;\r
2876 IFR_BLOCK_DATA *BlockData;\r
2877 IFR_DEFAULT_DATA *DefaultId;\r
2878 IFR_DEFAULT_DATA *DefaultValueData;\r
2879 UINTN Width;\r
2880 UINT8 *TmpBuffer;\r
2881\r
2882 BlockData = NULL;\r
2883 DataExist = FALSE;\r
2884\r
2885 //\r
2886 // Add length for <ConfigHdr> + '\0'\r
2887 //\r
2888 Length = StrLen (ConfigHdr) + 1;\r
2889\r
2890 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2891 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2892 //\r
2893 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
2894 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2895 //\r
2896 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
2897 \r
2898 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2899 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2900 ListEntry = &BlockData->DefaultValueEntry;\r
2901 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2902 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2903 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2904 continue;\r
2905 }\r
2906 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2907 //\r
2908 // Add length for "&Name1=zzzzzzzzzzzz"\r
2909 // |1|Name|1|Value|\r
2910 //\r
2911 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
2912 } else {\r
2913 //\r
2914 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
2915 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
2916 //\r
2917 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
2918 }\r
2919 DataExist = TRUE;\r
2920 }\r
2921 }\r
2922 }\r
2923 \r
2924 //\r
2925 // No default value is found. The default string doesn't exist.\r
2926 //\r
2927 if (!DataExist) {\r
2928 return EFI_SUCCESS;\r
2929 }\r
2930\r
2931 //\r
2932 // Allocate buffer for the entire <DefaultAltCfgResp>\r
2933 //\r
2934 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
2935 if (*DefaultAltCfgResp == NULL) {\r
2936 return EFI_OUT_OF_RESOURCES;\r
2937 }\r
2938 StringPtr = *DefaultAltCfgResp;\r
2939\r
2940 //\r
2941 // Start with <ConfigHdr>\r
2942 //\r
2943 StrCpyS (StringPtr, Length, ConfigHdr);\r
2944 StringPtr += StrLen (StringPtr);\r
2945\r
2946 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
2947 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
2948 //\r
2949 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
2950 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
2951 //\r
2952 UnicodeSPrint (\r
2953 StringPtr, \r
2954 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
2955 L"&%s&ALTCFG=%04X", \r
2956 ConfigHdr, \r
2957 DefaultId->DefaultId\r
2958 );\r
2959 StringPtr += StrLen (StringPtr);\r
2960\r
2961 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
2962 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
2963 ListEntry = &BlockData->DefaultValueEntry;\r
2964 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
2965 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
2966 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
2967 continue;\r
2968 }\r
2969 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2970 UnicodeSPrint (\r
2971 StringPtr, \r
2972 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
2973 L"&%s=", \r
2974 BlockData->Name\r
2975 );\r
2976 StringPtr += StrLen (StringPtr);\r
2977 } else {\r
2978 //\r
2979 // Add <BlockConfig>\r
2980 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
2981 //\r
2982 UnicodeSPrint (\r
2983 StringPtr, \r
2984 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
2985 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
2986 BlockData->Offset, \r
2987 BlockData->Width\r
2988 );\r
2989 StringPtr += StrLen (StringPtr);\r
2990 }\r
2991 Width = BlockData->Width;\r
2992 //\r
2993 // Convert Value to a hex string in "%x" format\r
2994 // NOTE: This is in the opposite byte that GUID and PATH use\r
2995 //\r
2996 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
2997 for (; Width > 0; Width--) {\r
2998 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);\r
2999 }\r
3000 }\r
3001 }\r
3002 }\r
3003\r
3004 HiiToLower (*DefaultAltCfgResp);\r
3005\r
3006 return EFI_SUCCESS;\r
3007}\r
3008\r
3009/**\r
3010 This function gets the full request string and full default value string by \r
3011 parsing IFR data in HII form packages. \r
3012 \r
3013 When Request points to NULL string, the request string and default value string \r
3014 for each varstore in form package will return. \r
3015\r
3016 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
3017 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
3018 @param Request Pointer to a null-terminated Unicode string in\r
3019 <ConfigRequest> format. When it doesn't contain\r
3020 any RequestElement, it will be updated to return \r
3021 the full RequestElement retrieved from IFR data.\r
3022 If it points to NULL, the request string for the first\r
3023 varstore in form package will be merged into a\r
3024 <MultiConfigRequest> format string and return. \r
3025 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
3026 <ConfigAltResp> format. When the pointer is to NULL,\r
3027 the full default value string retrieved from IFR data\r
3028 will return. When the pinter is to a string, the\r
3029 full default value string retrieved from IFR data\r
3030 will be merged into the input string and return.\r
3031 When Request points to NULL, the default value string \r
3032 for each varstore in form package will be merged into \r
3033 a <MultiConfigAltResp> format string and return.\r
3034 @param PointerProgress Optional parameter, it can be be NULL. \r
3035 When it is not NULL, if Request is NULL, it returns NULL. \r
3036 On return, points to a character in the Request\r
3037 string. Points to the string's null terminator if\r
3038 request was successful. Points to the most recent\r
3039 & before the first failing name / value pair (or\r
3040 the beginning of the string if the failure is in\r
3041 the first name / value pair) if the request was\r
3042 not successful.\r
3043 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3044 And AltCfgResp contains all default value string.\r
3045 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3046 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
3047 can't be found in Form package.\r
3048 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
3049 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3050\r
3051**/\r
3052EFI_STATUS\r
3053EFIAPI\r
3054GetFullStringFromHiiFormPackages (\r
3055 IN HII_DATABASE_RECORD *DataBaseRecord,\r
3056 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3057 IN OUT EFI_STRING *Request,\r
3058 IN OUT EFI_STRING *AltCfgResp,\r
3059 OUT EFI_STRING *PointerProgress OPTIONAL\r
3060 )\r
3061{\r
3062 EFI_STATUS Status;\r
3063 UINT8 *HiiFormPackage;\r
3064 UINTN PackageSize;\r
3065 IFR_BLOCK_DATA *RequestBlockArray;\r
3066 IFR_BLOCK_DATA *BlockData;\r
3067 IFR_DEFAULT_DATA *DefaultValueData;\r
3068 IFR_DEFAULT_DATA *DefaultId;\r
3069 IFR_DEFAULT_DATA *DefaultIdArray;\r
3070 IFR_VARSTORAGE_DATA *VarStorageData;\r
3071 EFI_STRING DefaultAltCfgResp;\r
3072 EFI_STRING ConfigHdr;\r
3073 EFI_STRING StringPtr;\r
3074 EFI_STRING Progress;\r
3075\r
3076 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
3077 return EFI_INVALID_PARAMETER;\r
3078 }\r
3079\r
3080 //\r
3081 // Initialize the local variables.\r
3082 //\r
3083 RequestBlockArray = NULL;\r
3084 DefaultIdArray = NULL;\r
3085 VarStorageData = NULL;\r
3086 DefaultAltCfgResp = NULL;\r
3087 ConfigHdr = NULL;\r
3088 HiiFormPackage = NULL;\r
3089 PackageSize = 0;\r
3090 Progress = *Request;\r
3091\r
3092 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
3093 if (EFI_ERROR (Status)) {\r
3094 goto Done;\r
3095 }\r
3096\r
3097 //\r
3098 // 1. Get the request block array by Request String when Request string containts the block array.\r
3099 //\r
3100 StringPtr = NULL;\r
3101 if (*Request != NULL) {\r
3102 StringPtr = *Request;\r
3103 //\r
3104 // Jump <ConfigHdr>\r
3105 //\r
3106 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3107 Status = EFI_INVALID_PARAMETER;\r
3108 goto Done;\r
3109 }\r
3110 StringPtr += StrLen (L"GUID=");\r
3111 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3112 StringPtr++;\r
3113 }\r
3114 if (*StringPtr == L'\0') {\r
3115 Status = EFI_INVALID_PARAMETER;\r
3116 goto Done;\r
3117 }\r
3118 StringPtr += StrLen (L"&NAME=");\r
3119 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3120 StringPtr++;\r
3121 }\r
3122 if (*StringPtr == L'\0') {\r
3123 Status = EFI_INVALID_PARAMETER;\r
3124 goto Done;\r
3125 }\r
3126 StringPtr += StrLen (L"&PATH=");\r
3127 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3128 StringPtr ++;\r
3129 }\r
3130\r
3131 if (*StringPtr == L'\0') {\r
3132 //\r
3133 // No request block is found.\r
3134 //\r
3135 StringPtr = NULL;\r
3136 }\r
3137 }\r
3138\r
3139 //\r
3140 // If StringPtr != NULL, get the request elements.\r
3141 //\r
3142 if (StringPtr != NULL) {\r
3143 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
3144 RequestBlockArray = GetBlockElement(StringPtr, &Progress);\r
3145 } else {\r
3146 RequestBlockArray = GetNameElement(StringPtr, &Progress);\r
3147 }\r
3148\r
3149 if (RequestBlockArray == NULL) {\r
3150 Status = EFI_INVALID_PARAMETER;\r
3151 goto Done;\r
3152 }\r
3153 }\r
3154\r
3155 //\r
3156 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
3157 //\r
3158 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
3159 if (DefaultIdArray == NULL) {\r
3160 Status = EFI_OUT_OF_RESOURCES;\r
3161 goto Done;\r
3162 }\r
3163 InitializeListHead (&DefaultIdArray->Entry);\r
3164\r
3165 //\r
3166 // Initialize VarStorageData to store the var store Block and Default value information.\r
3167 //\r
3168 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
3169 if (VarStorageData == NULL) {\r
3170 Status = EFI_OUT_OF_RESOURCES;\r
3171 goto Done;\r
3172 }\r
3173 InitializeListHead (&VarStorageData->Entry);\r
3174 InitializeListHead (&VarStorageData->BlockEntry);\r
3175\r
3176 //\r
3177 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
3178 //\r
3179\r
3180 //\r
3181 // Parse the opcode in form pacakge to get the default setting.\r
3182 //\r
3183 Status = ParseIfrData (DataBaseRecord->Handle,\r
3184 HiiFormPackage,\r
3185 (UINT32) PackageSize,\r
3186 *Request,\r
3187 RequestBlockArray,\r
3188 VarStorageData,\r
3189 DefaultIdArray);\r
3190 if (EFI_ERROR (Status)) {\r
3191 goto Done;\r
3192 }\r
3193\r
3194 //\r
3195 // No requested varstore in IFR data and directly return\r
3196 //\r
3197 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {\r
3198 Status = EFI_SUCCESS;\r
3199 goto Done;\r
3200 }\r
3201\r
3202 //\r
3203 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
3204 //\r
3205 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
3206 if (EFI_ERROR (Status)) {\r
3207 goto Done;\r
3208 }\r
3209\r
3210 if (RequestBlockArray == NULL) {\r
3211 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {\r
3212 goto Done;\r
3213 }\r
3214 }\r
3215\r
3216 //\r
3217 // 4. Construct Default Value string in AltResp according to request element.\r
3218 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
3219 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
3220 //\r
3221 Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
3222 if (EFI_ERROR (Status)) {\r
3223 goto Done;\r
3224 }\r
3225\r
3226 //\r
3227 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.\r
3228 //\r
3229 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
3230 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
3231 FreePool (DefaultAltCfgResp);\r
3232 } else if (*AltCfgResp == NULL) {\r
3233 *AltCfgResp = DefaultAltCfgResp;\r
3234 }\r
3235\r
3236Done:\r
3237 if (RequestBlockArray != NULL) {\r
3238 //\r
3239 // Free Link Array RequestBlockArray\r
3240 //\r
3241 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3242 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3243 RemoveEntryList (&BlockData->Entry);\r
3244 if (BlockData->Name != NULL) {\r
3245 FreePool (BlockData->Name);\r
3246 }\r
3247 FreePool (BlockData);\r
3248 }\r
3249\r
3250 FreePool (RequestBlockArray);\r
3251 }\r
3252\r
3253 if (VarStorageData != NULL) {\r
3254 //\r
3255 // Free link array VarStorageData\r
3256 //\r
3257 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
3258 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3259 RemoveEntryList (&BlockData->Entry);\r
3260 if (BlockData->Name != NULL) {\r
3261 FreePool (BlockData->Name);\r
3262 }\r
3263 //\r
3264 // Free default value link array\r
3265 //\r
3266 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
3267 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3268 RemoveEntryList (&DefaultValueData->Entry);\r
3269 FreePool (DefaultValueData);\r
3270 }\r
3271 FreePool (BlockData);\r
3272 }\r
3273 FreePool (VarStorageData);\r
3274 }\r
3275\r
3276 if (DefaultIdArray != NULL) {\r
3277 //\r
3278 // Free DefaultId Array\r
3279 //\r
3280 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
3281 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
3282 RemoveEntryList (&DefaultId->Entry);\r
3283 FreePool (DefaultId);\r
3284 }\r
3285 FreePool (DefaultIdArray);\r
3286 }\r
3287\r
3288 //\r
3289 // Free the allocated string \r
3290 //\r
3291 if (ConfigHdr != NULL) {\r
3292 FreePool (ConfigHdr);\r
3293 }\r
3294\r
3295 //\r
3296 // Free Pacakge data\r
3297 //\r
3298 if (HiiFormPackage != NULL) {\r
3299 FreePool (HiiFormPackage);\r
3300 }\r
3301\r
3302 if (PointerProgress != NULL) {\r
3303 if (*Request == NULL) {\r
3304 *PointerProgress = NULL;\r
3305 } else if (EFI_ERROR (Status)) {\r
3306 *PointerProgress = *Request;\r
3307 } else {\r
3308 *PointerProgress = *Request + StrLen (*Request);\r
3309 }\r
3310 }\r
3311\r
3312 return Status;\r
3313}\r
3314\r
3315/**\r
3316 This function gets the full request resp string by \r
3317 parsing IFR data in HII form packages.\r
3318\r
3319 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3320 instance.\r
3321 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3322 varstore data structure. \r
3323 @param Request Pointer to a null-terminated Unicode string in\r
3324 <ConfigRequest> format.\r
3325 @param RequestResp Pointer to a null-terminated Unicode string in\r
3326 <ConfigResp> format.\r
3327 @param AccessProgress On return, points to a character in the Request\r
3328 string. Points to the string's null terminator if\r
3329 request was successful. Points to the most recent\r
3330 & before the first failing name / value pair (or\r
3331 the beginning of the string if the failure is in\r
3332 the first name / value pair) if the request was\r
3333 not successful.\r
3334\r
3335 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3336 And AltCfgResp contains all default value string.\r
3337 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3338 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3339\r
3340**/\r
3341EFI_STATUS\r
3342GetConfigRespFromEfiVarStore (\r
3343 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3344 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3345 IN EFI_STRING Request,\r
3346 OUT EFI_STRING *RequestResp,\r
3347 OUT EFI_STRING *AccessProgress\r
3348 )\r
3349{\r
3350 EFI_STATUS Status;\r
3351 EFI_STRING VarStoreName;\r
3352 UINT8 *VarStore;\r
3353 UINTN BufferSize;\r
3354\r
3355 Status = EFI_SUCCESS;\r
3356 BufferSize = 0;\r
3357 VarStore = NULL;\r
3358 VarStoreName = NULL;\r
3359 *AccessProgress = Request;\r
3360 \r
3361 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3362 if (VarStoreName == NULL) {\r
3363 Status = EFI_OUT_OF_RESOURCES;\r
3364 goto Done;\r
3365 }\r
3366 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3367 \r
3368 \r
3369 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3370 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3371 goto Done;\r
3372 }\r
3373\r
3374 VarStore = AllocateZeroPool (BufferSize);\r
3375 ASSERT (VarStore != NULL);\r
3376 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3377 if (EFI_ERROR (Status)) {\r
3378 goto Done;\r
3379 }\r
3380\r
3381 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
3382 if (EFI_ERROR (Status)) {\r
3383 goto Done;\r
3384 }\r
3385\r
3386Done:\r
3387 if (VarStoreName != NULL) {\r
3388 FreePool (VarStoreName);\r
3389 }\r
3390\r
3391 if (VarStore != NULL) {\r
3392 FreePool (VarStore);\r
3393 }\r
3394\r
3395 return Status;\r
3396}\r
3397\r
3398\r
3399/**\r
3400 This function route the full request resp string for efi varstore. \r
3401\r
3402 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3403 instance.\r
3404 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
3405 varstore data structure. \r
3406 @param RequestResp Pointer to a null-terminated Unicode string in\r
3407 <ConfigResp> format.\r
3408 @param Result Pointer to a null-terminated Unicode string in\r
3409 <ConfigResp> format.\r
3410 \r
3411 @retval EFI_SUCCESS The Results string is set to the full request string.\r
3412 And AltCfgResp contains all default value string.\r
3413 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
3414 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
3415\r
3416**/\r
3417EFI_STATUS\r
3418RouteConfigRespForEfiVarStore (\r
3419 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3420 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
3421 IN EFI_STRING RequestResp,\r
3422 OUT EFI_STRING *Result\r
3423 )\r
3424{\r
3425 EFI_STATUS Status;\r
3426 EFI_STRING VarStoreName;\r
3427 UINT8 *VarStore;\r
3428 UINTN BufferSize;\r
3429 UINTN BlockSize;\r
3430\r
3431 Status = EFI_SUCCESS;\r
3432 BufferSize = 0;\r
3433 VarStore = NULL;\r
3434 VarStoreName = NULL;\r
3435\r
3436 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));\r
3437 if (VarStoreName == NULL) {\r
3438 Status = EFI_OUT_OF_RESOURCES;\r
3439 goto Done;\r
3440 }\r
3441 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);\r
3442 \r
3443 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
3444 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3445 goto Done;\r
3446 }\r
3447\r
3448 BlockSize = BufferSize;\r
3449 VarStore = AllocateZeroPool (BufferSize);\r
3450 ASSERT (VarStore != NULL);\r
3451 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
3452 if (EFI_ERROR (Status)) {\r
3453 goto Done;\r
3454 }\r
3455\r
3456 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
3457 if (EFI_ERROR (Status)) {\r
3458 goto Done;\r
3459 }\r
3460\r
3461 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
3462 if (EFI_ERROR (Status)) {\r
3463 goto Done;\r
3464 }\r
3465\r
3466Done:\r
3467 if (VarStoreName != NULL) {\r
3468 FreePool (VarStoreName);\r
3469 }\r
3470\r
3471 if (VarStore != NULL) {\r
3472 FreePool (VarStore);\r
3473 }\r
3474\r
3475 return Status;\r
3476}\r
3477\r
3478/**\r
3479 Validate the config request elements.\r
3480\r
3481 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3482 without configHdr field.\r
3483\r
3484 @retval CHAR16 * THE first Name/value pair not correct.\r
3485 @retval NULL Success parse the name/value pair\r
3486**/\r
3487CHAR16 *\r
3488OffsetWidthValidate (\r
3489 CHAR16 *ConfigElements\r
3490 )\r
3491{\r
3492 CHAR16 *StringPtr;\r
3493 CHAR16 *RetVal;\r
3494\r
3495 StringPtr = ConfigElements;\r
3496\r
3497 while (1) {\r
3498 RetVal = StringPtr;\r
3499 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3500 return RetVal;\r
3501 }\r
3502\r
3503 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3504 StringPtr++;\r
3505 }\r
3506 if (*StringPtr == L'\0') {\r
3507 return RetVal;\r
3508 }\r
3509\r
3510 StringPtr += StrLen (L"&WIDTH=");\r
3511 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
3512 StringPtr ++;\r
3513 }\r
3514\r
3515 if (*StringPtr == L'\0') {\r
3516 return NULL;\r
3517 }\r
3518 }\r
3519}\r
3520\r
3521/**\r
3522 Validate the config request elements.\r
3523\r
3524 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
3525 without configHdr field.\r
3526\r
3527 @retval CHAR16 * THE first Name/value pair not correct.\r
3528 @retval NULL Success parse the name/value pair\r
3529\r
3530**/\r
3531CHAR16 *\r
3532NameValueValidate (\r
3533 CHAR16 *ConfigElements\r
3534 )\r
3535{\r
3536 CHAR16 *StringPtr;\r
3537 CHAR16 *RetVal;\r
3538\r
3539 StringPtr = ConfigElements;\r
3540\r
3541 while (1) {\r
3542 RetVal = StringPtr;\r
3543 if (*StringPtr != L'&') {\r
3544 return RetVal;\r
3545 }\r
3546 StringPtr += 1;\r
3547\r
3548 StringPtr = StrStr (StringPtr, L"&");\r
3549 \r
3550 if (StringPtr == NULL) {\r
3551 return NULL;\r
3552 }\r
3553 }\r
3554}\r
3555\r
3556/**\r
3557 Validate the config request string.\r
3558\r
3559 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
3560\r
3561 @retval CHAR16 * THE first element not correct.\r
3562 @retval NULL Success parse the name/value pair\r
3563\r
3564**/\r
3565CHAR16 *\r
3566ConfigRequestValidate (\r
3567 CHAR16 *ConfigRequest\r
3568 )\r
3569{\r
3570 BOOLEAN HasNameField;\r
3571 CHAR16 *StringPtr;\r
3572\r
3573 HasNameField = TRUE;\r
3574 StringPtr = ConfigRequest;\r
3575\r
3576 //\r
3577 // Check <ConfigHdr>\r
3578 //\r
3579 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3580 return ConfigRequest;\r
3581 }\r
3582 StringPtr += StrLen (L"GUID=");\r
3583 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
3584 StringPtr++;\r
3585 }\r
3586 if (*StringPtr == L'\0') {\r
3587 return ConfigRequest;\r
3588 }\r
3589 StringPtr += StrLen (L"&NAME=");\r
3590 if (*StringPtr == L'&') {\r
3591 HasNameField = FALSE;\r
3592 }\r
3593 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
3594 StringPtr++;\r
3595 }\r
3596 if (*StringPtr == L'\0') {\r
3597 return ConfigRequest;\r
3598 }\r
3599 StringPtr += StrLen (L"&PATH=");\r
3600 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
3601 StringPtr ++;\r
3602 }\r
3603\r
3604 if (*StringPtr == L'\0') {\r
3605 return NULL;\r
3606 }\r
3607\r
3608 if (HasNameField) {\r
3609 //\r
3610 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
3611 //\r
3612 return OffsetWidthValidate(StringPtr);\r
3613 } else {\r
3614 //\r
3615 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
3616 //\r
3617 return NameValueValidate(StringPtr);\r
3618 }\r
3619}\r
3620\r
3621/**\r
3622 This function allows a caller to extract the current configuration\r
3623 for one or more named elements from one or more drivers.\r
3624\r
3625 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3626 instance.\r
3627 @param Request A null-terminated Unicode string in\r
3628 <MultiConfigRequest> format.\r
3629 @param Progress On return, points to a character in the Request\r
3630 string. Points to the string's null terminator if\r
3631 request was successful. Points to the most recent\r
3632 & before the first failing name / value pair (or\r
3633 the beginning of the string if the failure is in\r
3634 the first name / value pair) if the request was\r
3635 not successful.\r
3636 @param Results Null-terminated Unicode string in\r
3637 <MultiConfigAltResp> format which has all values\r
3638 filled in for the names in the Request string.\r
3639 String to be allocated by the called function.\r
3640\r
3641 @retval EFI_SUCCESS The Results string is filled with the values\r
3642 corresponding to all requested names.\r
3643 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3644 results that must be stored awaiting possible\r
3645 future protocols.\r
3646 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
3647 Progress set to the "G" in "GUID" of the routing\r
3648 header that doesn't match. Note: There is no\r
3649 requirement that all routing data be validated\r
3650 before any configuration extraction.\r
3651 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
3652 parameter would result in this type of error. The\r
3653 Progress parameter is set to NULL.\r
3654 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
3655 before the error or the beginning of the string.\r
3656 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII\r
3657 Configuration Access Protocol returned \r
3658 EFI_INVALID_PARAMETER. Progress set to most recent\r
3659 & before the error or the beginning of the string.\r
3660\r
3661**/\r
3662EFI_STATUS\r
3663EFIAPI\r
3664HiiConfigRoutingExtractConfig (\r
3665 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3666 IN CONST EFI_STRING Request,\r
3667 OUT EFI_STRING *Progress,\r
3668 OUT EFI_STRING *Results\r
3669 )\r
3670{\r
3671 HII_DATABASE_PRIVATE_DATA *Private;\r
3672 EFI_STRING StringPtr;\r
3673 EFI_STRING ConfigRequest;\r
3674 UINTN Length;\r
3675 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3676 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
3677 EFI_STATUS Status;\r
3678 LIST_ENTRY *Link;\r
3679 HII_DATABASE_RECORD *Database;\r
3680 UINT8 *DevicePathPkg;\r
3681 UINT8 *CurrentDevicePath;\r
3682 EFI_HANDLE DriverHandle;\r
3683 EFI_HII_HANDLE HiiHandle;\r
3684 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3685 EFI_STRING AccessProgress;\r
3686 EFI_STRING AccessResults;\r
3687 EFI_STRING DefaultResults;\r
3688 BOOLEAN FirstElement;\r
3689 BOOLEAN IfrDataParsedFlag;\r
3690 BOOLEAN IsEfiVarStore;\r
3691 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
3692 EFI_STRING ErrorPtr;\r
3693 UINTN DevicePathSize;\r
3694\r
3695 if (This == NULL || Progress == NULL || Results == NULL) {\r
3696 return EFI_INVALID_PARAMETER;\r
3697 }\r
3698\r
3699 if (Request == NULL) {\r
3700 *Progress = NULL;\r
3701 return EFI_INVALID_PARAMETER;\r
3702 }\r
3703\r
3704 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3705 StringPtr = Request;\r
3706 *Progress = StringPtr;\r
3707 DefaultResults = NULL;\r
3708 ConfigRequest = NULL;\r
3709 Status = EFI_SUCCESS;\r
3710 AccessResults = NULL;\r
3711 AccessProgress = NULL;\r
3712 DevicePath = NULL;\r
3713 IfrDataParsedFlag = FALSE;\r
3714 IsEfiVarStore = FALSE;\r
3715 EfiVarStoreInfo = NULL;\r
3716\r
3717 //\r
3718 // The first element of <MultiConfigRequest> should be\r
3719 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
3720 //\r
3721 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
3722 return EFI_INVALID_PARAMETER;\r
3723 }\r
3724\r
3725 FirstElement = TRUE;\r
3726\r
3727 //\r
3728 // Allocate a fix length of memory to store Results. Reallocate memory for\r
3729 // Results if this fix length is insufficient.\r
3730 //\r
3731 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
3732 if (*Results == NULL) {\r
3733 return EFI_OUT_OF_RESOURCES;\r
3734 }\r
3735\r
3736 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
3737 //\r
3738 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
3739 // or most recent & before the error.\r
3740 //\r
3741 if (StringPtr == Request) {\r
3742 *Progress = StringPtr;\r
3743 } else {\r
3744 *Progress = StringPtr - 1;\r
3745 }\r
3746\r
3747 //\r
3748 // Process each <ConfigRequest> of <MultiConfigRequest>\r
3749 //\r
3750 Length = CalculateConfigStringLen (StringPtr);\r
3751 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
3752 if (ConfigRequest == NULL) {\r
3753 Status = EFI_OUT_OF_RESOURCES;\r
3754 goto Done;\r
3755 }\r
3756 *(ConfigRequest + Length) = 0;\r
3757\r
3758 //\r
3759 // Get the UEFI device path\r
3760 //\r
3761 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
3762 if (EFI_ERROR (Status)) {\r
3763 goto Done;\r
3764 }\r
3765\r
3766 //\r
3767 // Find driver which matches the routing data.\r
3768 //\r
3769 DriverHandle = NULL;\r
3770 HiiHandle = NULL;\r
3771 Database = NULL;\r
3772 for (Link = Private->DatabaseList.ForwardLink;\r
3773 Link != &Private->DatabaseList;\r
3774 Link = Link->ForwardLink\r
3775 ) {\r
3776 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3777 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
3778 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
3779 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
3780 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {\r
3781 DriverHandle = Database->DriverHandle;\r
3782 HiiHandle = Database->Handle;\r
3783 break;\r
3784 }\r
3785 }\r
3786 }\r
3787 \r
3788 //\r
3789 // Try to find driver handle by device path.\r
3790 //\r
3791 if (DriverHandle == NULL) {\r
3792 TempDevicePath = DevicePath;\r
3793 Status = gBS->LocateDevicePath (\r
3794 &gEfiDevicePathProtocolGuid,\r
3795 &TempDevicePath,\r
3796 &DriverHandle\r
3797 );\r
3798 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
3799 //\r
3800 // Routing data does not match any known driver.\r
3801 // Set Progress to the 'G' in "GUID" of the routing header.\r
3802 //\r
3803 *Progress = StringPtr;\r
3804 Status = EFI_NOT_FOUND;\r
3805 goto Done;\r
3806 }\r
3807 }\r
3808\r
3809 //\r
3810 // Validate ConfigRequest String.\r
3811 //\r
3812 ErrorPtr = ConfigRequestValidate(ConfigRequest);\r
3813 if (ErrorPtr != NULL) {\r
3814 *Progress = StrStr (StringPtr, ErrorPtr);\r
3815 Status = EFI_INVALID_PARAMETER;\r
3816 goto Done;\r
3817 }\r
3818\r
3819 //\r
3820 // Check whether ConfigRequest contains request string.\r
3821 //\r
3822 IfrDataParsedFlag = FALSE;\r
3823 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {\r
3824 //\r
3825 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
3826 //\r
3827 IfrDataParsedFlag = TRUE;\r
3828 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
3829 if (EFI_ERROR (Status)) {\r
3830 //\r
3831 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3832 // Map it to the progress on <MultiConfigRequest> then return it.\r
3833 //\r
3834 ASSERT (AccessProgress != NULL);\r
3835 *Progress = StrStr (StringPtr, AccessProgress);\r
3836 goto Done;\r
3837 }\r
3838 //\r
3839 // Not any request block is found.\r
3840 //\r
3841 if (!GetElementsFromRequest(ConfigRequest)) {\r
3842 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
3843 goto NextConfigString;\r
3844 }\r
3845 }\r
3846\r
3847 //\r
3848 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
3849 //\r
3850 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
3851 if (EFI_ERROR (Status)) {\r
3852 goto Done;\r
3853 }\r
3854 \r
3855 if (IsEfiVarStore) {\r
3856 //\r
3857 // Call the GetVariable function to extract settings.\r
3858 //\r
3859 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
3860 FreePool (EfiVarStoreInfo);\r
3861 } else {\r
3862 //\r
3863 // Call corresponding ConfigAccess protocol to extract settings\r
3864 //\r
3865 Status = gBS->HandleProtocol (\r
3866 DriverHandle,\r
3867 &gEfiHiiConfigAccessProtocolGuid,\r
3868 (VOID **) &ConfigAccess\r
3869 );\r
3870 ASSERT_EFI_ERROR (Status);\r
3871\r
3872 Status = ConfigAccess->ExtractConfig (\r
3873 ConfigAccess,\r
3874 ConfigRequest,\r
3875 &AccessProgress,\r
3876 &AccessResults\r
3877 );\r
3878 }\r
3879 if (EFI_ERROR (Status)) {\r
3880 //\r
3881 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
3882 // Map it to the progress on <MultiConfigRequest> then return it.\r
3883 //\r
3884 *Progress = StrStr (StringPtr, AccessProgress);\r
3885 goto Done;\r
3886 }\r
3887\r
3888 //\r
3889 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
3890 // which seperates the first <ConfigAltResp> and the following ones.\r
3891 //\r
3892 ASSERT (*AccessProgress == 0);\r
3893\r
3894 //\r
3895 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
3896 //\r
3897 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
3898 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
3899 ASSERT_EFI_ERROR (Status);\r
3900 }\r
3901\r
3902 FreePool (DevicePath);\r
3903 DevicePath = NULL;\r
3904\r
3905 if (DefaultResults != NULL) {\r
3906 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
3907 ASSERT_EFI_ERROR (Status);\r
3908 FreePool (DefaultResults);\r
3909 DefaultResults = NULL;\r
3910 }\r
3911 \r
3912NextConfigString:\r
3913 if (!FirstElement) {\r
3914 Status = AppendToMultiString (Results, L"&");\r
3915 ASSERT_EFI_ERROR (Status);\r
3916 }\r
3917 \r
3918 Status = AppendToMultiString (Results, AccessResults);\r
3919 ASSERT_EFI_ERROR (Status);\r
3920\r
3921 FirstElement = FALSE;\r
3922\r
3923 FreePool (AccessResults);\r
3924 AccessResults = NULL;\r
3925 FreePool (ConfigRequest);\r
3926 ConfigRequest = NULL;\r
3927\r
3928 //\r
3929 // Go to next <ConfigRequest> (skip '&').\r
3930 //\r
3931 StringPtr += Length;\r
3932 if (*StringPtr == 0) {\r
3933 *Progress = StringPtr;\r
3934 break;\r
3935 }\r
3936\r
3937 StringPtr++;\r
3938 }\r
3939\r
3940Done:\r
3941 if (EFI_ERROR (Status)) {\r
3942 FreePool (*Results);\r
3943 *Results = NULL;\r
3944 }\r
3945 \r
3946 if (ConfigRequest != NULL) {\r
3947 FreePool (ConfigRequest);\r
3948 }\r
3949 \r
3950 if (AccessResults != NULL) {\r
3951 FreePool (AccessResults);\r
3952 }\r
3953 \r
3954 if (DefaultResults != NULL) {\r
3955 FreePool (DefaultResults);\r
3956 }\r
3957 \r
3958 if (DevicePath != NULL) {\r
3959 FreePool (DevicePath);\r
3960 } \r
3961\r
3962 return Status;\r
3963}\r
3964\r
3965\r
3966/**\r
3967 This function allows the caller to request the current configuration for the\r
3968 entirety of the current HII database and returns the data in a\r
3969 null-terminated Unicode string.\r
3970\r
3971 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
3972 instance.\r
3973 @param Results Null-terminated Unicode string in\r
3974 <MultiConfigAltResp> format which has all values\r
3975 filled in for the entirety of the current HII \r
3976 database. String to be allocated by the called \r
3977 function. De-allocation is up to the caller.\r
3978\r
3979 @retval EFI_SUCCESS The Results string is filled with the values\r
3980 corresponding to all requested names.\r
3981 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
3982 results that must be stored awaiting possible\r
3983 future protocols.\r
3984 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
3985 parameter would result in this type of error.\r
3986\r
3987**/\r
3988EFI_STATUS\r
3989EFIAPI\r
3990HiiConfigRoutingExportConfig (\r
3991 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
3992 OUT EFI_STRING *Results\r
3993 )\r
3994{\r
3995 EFI_STATUS Status;\r
3996 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
3997 EFI_STRING AccessResults;\r
3998 EFI_STRING Progress;\r
3999 EFI_STRING StringPtr;\r
4000 EFI_STRING ConfigRequest;\r
4001 UINTN Index;\r
4002 EFI_HANDLE *ConfigAccessHandles;\r
4003 UINTN NumberConfigAccessHandles;\r
4004 BOOLEAN FirstElement;\r
4005 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
4006 EFI_HII_HANDLE HiiHandle;\r
4007 EFI_STRING DefaultResults;\r
4008 HII_DATABASE_PRIVATE_DATA *Private;\r
4009 LIST_ENTRY *Link;\r
4010 HII_DATABASE_RECORD *Database;\r
4011 UINT8 *DevicePathPkg;\r
4012 UINT8 *CurrentDevicePath;\r
4013 BOOLEAN IfrDataParsedFlag;\r
4014\r
4015 if (This == NULL || Results == NULL) {\r
4016 return EFI_INVALID_PARAMETER;\r
4017 }\r
4018\r
4019 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4020\r
4021 //\r
4022 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4023 // Results if this fix length is insufficient.\r
4024 //\r
4025 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4026 if (*Results == NULL) {\r
4027 return EFI_OUT_OF_RESOURCES;\r
4028 }\r
4029\r
4030 NumberConfigAccessHandles = 0;\r
4031 Status = gBS->LocateHandleBuffer (\r
4032 ByProtocol,\r
4033 &gEfiHiiConfigAccessProtocolGuid,\r
4034 NULL,\r
4035 &NumberConfigAccessHandles,\r
4036 &ConfigAccessHandles\r
4037 );\r
4038 if (EFI_ERROR (Status)) {\r
4039 return Status;\r
4040 }\r
4041\r
4042 FirstElement = TRUE;\r
4043\r
4044 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
4045 Status = gBS->HandleProtocol (\r
4046 ConfigAccessHandles[Index],\r
4047 &gEfiHiiConfigAccessProtocolGuid,\r
4048 (VOID **) &ConfigAccess\r
4049 );\r
4050 if (EFI_ERROR (Status)) {\r
4051 continue;\r
4052 }\r
4053\r
4054 //\r
4055 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
4056 //\r
4057 IfrDataParsedFlag = FALSE;\r
4058 Progress = NULL;\r
4059 HiiHandle = NULL;\r
4060 DefaultResults = NULL;\r
4061 Database = NULL;\r
4062 ConfigRequest = NULL;\r
4063 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
4064 if (DevicePath != NULL) {\r
4065 for (Link = Private->DatabaseList.ForwardLink;\r
4066 Link != &Private->DatabaseList;\r
4067 Link = Link->ForwardLink\r
4068 ) {\r
4069 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4070 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4071 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
4072 if (CompareMem (\r
4073 DevicePath,\r
4074 CurrentDevicePath,\r
4075 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
4076 ) == 0) {\r
4077 HiiHandle = Database->Handle;\r
4078 break;\r
4079 }\r
4080 }\r
4081 }\r
4082 }\r
4083\r
4084 Status = ConfigAccess->ExtractConfig (\r
4085 ConfigAccess,\r
4086 NULL,\r
4087 &Progress,\r
4088 &AccessResults\r
4089 );\r
4090 if (EFI_ERROR (Status)) {\r
4091 //\r
4092 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
4093 //\r
4094 if (HiiHandle != NULL && DevicePath != NULL) {\r
4095 IfrDataParsedFlag = TRUE;\r
4096 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
4097 //\r
4098 // Get the full request string to get the Current setting again.\r
4099 //\r
4100 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
4101 Status = ConfigAccess->ExtractConfig (\r
4102 ConfigAccess,\r
4103 ConfigRequest,\r
4104 &Progress,\r
4105 &AccessResults\r
4106 );\r
4107 FreePool (ConfigRequest);\r
4108 } else {\r
4109 Status = EFI_NOT_FOUND;\r
4110 }\r
4111 }\r
4112 }\r
4113\r
4114 if (!EFI_ERROR (Status)) {\r
4115 //\r
4116 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
4117 //\r
4118 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
4119 StringPtr = StrStr (AccessResults, L"&GUID=");\r
4120 if (StringPtr != NULL) {\r
4121 *StringPtr = 0;\r
4122 }\r
4123 if (GetElementsFromRequest (AccessResults)) {\r
4124 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
4125 ASSERT_EFI_ERROR (Status);\r
4126 }\r
4127 if (StringPtr != NULL) {\r
4128 *StringPtr = L'&';\r
4129 }\r
4130 }\r
4131 //\r
4132 // Merge the default sting from IFR code into the got setting from driver.\r
4133 //\r
4134 if (DefaultResults != NULL) {\r
4135 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
4136 ASSERT_EFI_ERROR (Status);\r
4137 FreePool (DefaultResults);\r
4138 DefaultResults = NULL;\r
4139 }\r
4140 \r
4141 //\r
4142 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4143 // which seperates the first <ConfigAltResp> and the following ones. \r
4144 //\r
4145 if (!FirstElement) {\r
4146 Status = AppendToMultiString (Results, L"&");\r
4147 ASSERT_EFI_ERROR (Status);\r
4148 }\r
4149 \r
4150 Status = AppendToMultiString (Results, AccessResults);\r
4151 ASSERT_EFI_ERROR (Status);\r
4152\r
4153 FirstElement = FALSE;\r
4154 \r
4155 FreePool (AccessResults);\r
4156 AccessResults = NULL;\r
4157 }\r
4158 }\r
4159 FreePool (ConfigAccessHandles);\r
4160\r
4161 return EFI_SUCCESS; \r
4162}\r
4163\r
4164\r
4165/**\r
4166 This function processes the results of processing forms and routes it to the\r
4167 appropriate handlers or storage.\r
4168\r
4169 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4170 instance.\r
4171 @param Configuration A null-terminated Unicode string in\r
4172 <MulltiConfigResp> format.\r
4173 @param Progress A pointer to a string filled in with the offset of\r
4174 the most recent & before the first failing name /\r
4175 value pair (or the beginning of the string if the\r
4176 failure is in the first name / value pair) or the\r
4177 terminating NULL if all was successful.\r
4178\r
4179 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
4180 distribution.\r
4181 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
4182 results that must be stored awaiting possible\r
4183 future protocols.\r
4184 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
4185 would result in this type of error.\r
4186 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4187 found.\r
4188\r
4189**/\r
4190EFI_STATUS\r
4191EFIAPI\r
4192HiiConfigRoutingRouteConfig (\r
4193 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4194 IN CONST EFI_STRING Configuration,\r
4195 OUT EFI_STRING *Progress\r
4196 )\r
4197{\r
4198 HII_DATABASE_PRIVATE_DATA *Private;\r
4199 EFI_STRING StringPtr;\r
4200 EFI_STRING ConfigResp;\r
4201 UINTN Length;\r
4202 EFI_STATUS Status;\r
4203 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
4204 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
4205 LIST_ENTRY *Link;\r
4206 HII_DATABASE_RECORD *Database;\r
4207 UINT8 *DevicePathPkg;\r
4208 UINT8 *CurrentDevicePath;\r
4209 EFI_HANDLE DriverHandle;\r
4210 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4211 EFI_STRING AccessProgress;\r
4212 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4213 BOOLEAN IsEfiVarstore;\r
4214 UINTN DevicePathSize;\r
4215\r
4216 if (This == NULL || Progress == NULL) {\r
4217 return EFI_INVALID_PARAMETER;\r
4218 }\r
4219\r
4220 if (Configuration == NULL) {\r
4221 *Progress = NULL;\r
4222 return EFI_INVALID_PARAMETER;\r
4223 }\r
4224\r
4225 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4226 StringPtr = Configuration;\r
4227 *Progress = StringPtr;\r
4228 Database = NULL;\r
4229 AccessProgress = NULL;\r
4230 EfiVarStoreInfo= NULL;\r
4231 IsEfiVarstore = FALSE;\r
4232\r
4233 //\r
4234 // The first element of <MultiConfigResp> should be\r
4235 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4236 //\r
4237 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4238 return EFI_INVALID_PARAMETER;\r
4239 }\r
4240\r
4241 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4242 //\r
4243 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
4244 // or most recent & before the error.\r
4245 //\r
4246 if (StringPtr == Configuration) {\r
4247 *Progress = StringPtr;\r
4248 } else {\r
4249 *Progress = StringPtr - 1;\r
4250 }\r
4251\r
4252 //\r
4253 // Process each <ConfigResp> of <MultiConfigResp>\r
4254 //\r
4255 Length = CalculateConfigStringLen (StringPtr);\r
4256 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4257 if (ConfigResp == NULL) {\r
4258 return EFI_OUT_OF_RESOURCES;\r
4259 }\r
4260 //\r
4261 // Append '\0' to the end of ConfigRequest\r
4262 //\r
4263 *(ConfigResp + Length) = 0;\r
4264\r
4265 //\r
4266 // Get the UEFI device path\r
4267 //\r
4268 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
4269 if (EFI_ERROR (Status)) {\r
4270 FreePool (ConfigResp);\r
4271 return Status;\r
4272 }\r
4273\r
4274 //\r
4275 // Find driver which matches the routing data.\r
4276 //\r
4277 DriverHandle = NULL;\r
4278 for (Link = Private->DatabaseList.ForwardLink;\r
4279 Link != &Private->DatabaseList;\r
4280 Link = Link->ForwardLink\r
4281 ) {\r
4282 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4283\r
4284 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4285 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
4286 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
4287 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {\r
4288 DriverHandle = Database->DriverHandle;\r
4289 break;\r
4290 }\r
4291 }\r
4292 }\r
4293\r
4294 //\r
4295 // Try to find driver handle by device path.\r
4296 //\r
4297 if (DriverHandle == NULL) {\r
4298 TempDevicePath = DevicePath;\r
4299 Status = gBS->LocateDevicePath (\r
4300 &gEfiDevicePathProtocolGuid,\r
4301 &TempDevicePath,\r
4302 &DriverHandle\r
4303 );\r
4304 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4305 //\r
4306 // Routing data does not match any known driver.\r
4307 // Set Progress to the 'G' in "GUID" of the routing header.\r
4308 //\r
4309 FreePool (DevicePath);\r
4310 *Progress = StringPtr;\r
4311 FreePool (ConfigResp);\r
4312 return EFI_NOT_FOUND;\r
4313 }\r
4314 }\r
4315\r
4316 FreePool (DevicePath);\r
4317\r
4318 //\r
4319 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
4320 //\r
4321 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
4322 if (EFI_ERROR (Status)) {\r
4323 return Status;\r
4324 }\r
4325\r
4326 if (IsEfiVarstore) {\r
4327 //\r
4328 // Call the SetVariable function to route settings.\r
4329 // \r
4330 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
4331 FreePool (EfiVarStoreInfo);\r
4332 } else {\r
4333 //\r
4334 // Call corresponding ConfigAccess protocol to route settings\r
4335 //\r
4336 Status = gBS->HandleProtocol (\r
4337 DriverHandle,\r
4338 &gEfiHiiConfigAccessProtocolGuid,\r
4339 (VOID **) &ConfigAccess\r
4340 );\r
4341 ASSERT_EFI_ERROR (Status);\r
4342\r
4343 Status = ConfigAccess->RouteConfig (\r
4344 ConfigAccess,\r
4345 ConfigResp,\r
4346 &AccessProgress\r
4347 );\r
4348 }\r
4349 if (EFI_ERROR (Status)) {\r
4350 ASSERT (AccessProgress != NULL);\r
4351 //\r
4352 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
4353 // Map it to the progress on <MultiConfigResp> then return it.\r
4354 //\r
4355 *Progress = StrStr (StringPtr, AccessProgress);\r
4356\r
4357 FreePool (ConfigResp);\r
4358 return Status;\r
4359 }\r
4360\r
4361 FreePool (ConfigResp);\r
4362 ConfigResp = NULL;\r
4363\r
4364 //\r
4365 // Go to next <ConfigResp> (skip '&').\r
4366 //\r
4367 StringPtr += Length;\r
4368 if (*StringPtr == 0) {\r
4369 *Progress = StringPtr;\r
4370 break;\r
4371 }\r
4372\r
4373 StringPtr++;\r
4374\r
4375 }\r
4376\r
4377 return EFI_SUCCESS;\r
4378}\r
4379\r
4380\r
4381/**\r
4382 This helper function is to be called by drivers to map configuration data\r
4383 stored in byte array ("block") formats such as UEFI Variables into current\r
4384 configuration strings.\r
4385\r
4386 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4387 instance.\r
4388 @param ConfigRequest A null-terminated Unicode string in\r
4389 <ConfigRequest> format.\r
4390 @param Block Array of bytes defining the block's configuration.\r
4391 @param BlockSize Length in bytes of Block.\r
4392 @param Config Filled-in configuration string. String allocated\r
4393 by the function. Returned only if call is\r
4394 successful. It is <ConfigResp> string format.\r
4395 @param Progress A pointer to a string filled in with the offset of\r
4396 the most recent & before the first failing\r
4397 name/value pair (or the beginning of the string if\r
4398 the failure is in the first name / value pair) or\r
4399 the terminating NULL if all was successful.\r
4400\r
4401 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4402 terminator at the end of the ConfigRequest\r
4403 string.\r
4404 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4405 points to the first character of ConfigRequest.\r
4406 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
4407 Block parameter would result in this type of\r
4408 error. Progress points to the first character of\r
4409 ConfigRequest.\r
4410 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
4411 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
4412 Block is left updated and Progress points at\r
4413 the "&" preceding the first non-<BlockName>.\r
4414\r
4415**/\r
4416EFI_STATUS\r
4417EFIAPI\r
4418HiiBlockToConfig (\r
4419 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4420 IN CONST EFI_STRING ConfigRequest,\r
4421 IN CONST UINT8 *Block,\r
4422 IN CONST UINTN BlockSize,\r
4423 OUT EFI_STRING *Config,\r
4424 OUT EFI_STRING *Progress\r
4425 )\r
4426{\r
4427 HII_DATABASE_PRIVATE_DATA *Private;\r
4428 EFI_STRING StringPtr;\r
4429 UINTN Length;\r
4430 EFI_STATUS Status;\r
4431 EFI_STRING TmpPtr;\r
4432 UINT8 *TmpBuffer;\r
4433 UINTN Offset;\r
4434 UINTN Width;\r
4435 UINT8 *Value;\r
4436 EFI_STRING ValueStr;\r
4437 EFI_STRING ConfigElement;\r
4438 UINTN Index;\r
4439 UINT8 *TemBuffer;\r
4440 CHAR16 *TemString;\r
4441 CHAR16 TemChar;\r
4442\r
4443 TmpBuffer = NULL;\r
4444\r
4445 if (This == NULL || Progress == NULL || Config == NULL) {\r
4446 return EFI_INVALID_PARAMETER;\r
4447 }\r
4448\r
4449 if (Block == NULL || ConfigRequest == NULL) {\r
4450 *Progress = ConfigRequest;\r
4451 return EFI_INVALID_PARAMETER;\r
4452 }\r
4453\r
4454\r
4455 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4456 ASSERT (Private != NULL);\r
4457\r
4458 StringPtr = ConfigRequest;\r
4459 ValueStr = NULL;\r
4460 Value = NULL;\r
4461 ConfigElement = NULL;\r
4462\r
4463 //\r
4464 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4465 // Results if this fix length is insufficient.\r
4466 //\r
4467 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4468 if (*Config == NULL) {\r
4469 return EFI_OUT_OF_RESOURCES;\r
4470 }\r
4471\r
4472 //\r
4473 // Jump <ConfigHdr>\r
4474 //\r
4475 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4476 *Progress = StringPtr;\r
4477 Status = EFI_INVALID_PARAMETER;\r
4478 goto Exit;\r
4479 }\r
4480 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4481 StringPtr++;\r
4482 }\r
4483 if (*StringPtr == 0) {\r
4484 *Progress = StringPtr - 1;\r
4485 Status = EFI_INVALID_PARAMETER;\r
4486 goto Exit;\r
4487 }\r
4488\r
4489 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4490 StringPtr++;\r
4491 }\r
4492 if (*StringPtr == 0) {\r
4493 *Progress = StringPtr;\r
4494\r
4495 AppendToMultiString(Config, ConfigRequest);\r
4496 HiiToLower (*Config);\r
4497\r
4498 return EFI_SUCCESS;\r
4499 }\r
4500 //\r
4501 // Skip '&'\r
4502 //\r
4503 StringPtr++;\r
4504\r
4505 //\r
4506 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
4507 //\r
4508 TemChar = *StringPtr;\r
4509 *StringPtr = '\0';\r
4510 AppendToMultiString(Config, ConfigRequest);\r
4511 *StringPtr = TemChar;\r
4512\r
4513 //\r
4514 // Parse each <RequestElement> if exists\r
4515 // Only <BlockName> format is supported by this help function.\r
4516 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
4517 //\r
4518 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
4519 //\r
4520 // Back up the header of one <BlockName>\r
4521 //\r
4522 TmpPtr = StringPtr;\r
4523\r
4524 StringPtr += StrLen (L"OFFSET=");\r
4525 //\r
4526 // Get Offset\r
4527 //\r
4528 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
4529 if (EFI_ERROR (Status)) {\r
4530 *Progress = TmpPtr - 1;\r
4531 goto Exit;\r
4532 }\r
4533 Offset = 0;\r
4534 CopyMem (\r
4535 &Offset,\r
4536 TmpBuffer,\r
4537 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4538 );\r
4539 FreePool (TmpBuffer);\r
4540\r
4541 StringPtr += Length;\r
4542 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4543 *Progress = TmpPtr - 1;\r
4544 Status = EFI_INVALID_PARAMETER;\r
4545 goto Exit;\r
4546 }\r
4547 StringPtr += StrLen (L"&WIDTH=");\r
4548\r
4549 //\r
4550 // Get Width\r
4551 //\r
4552 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
4553 if (EFI_ERROR (Status)) {\r
4554 *Progress = TmpPtr - 1;\r
4555 goto Exit;\r
4556 }\r
4557 Width = 0;\r
4558 CopyMem (\r
4559 &Width,\r
4560 TmpBuffer,\r
4561 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4562 );\r
4563 FreePool (TmpBuffer);\r
4564\r
4565 StringPtr += Length;\r
4566 if (*StringPtr != 0 && *StringPtr != L'&') {\r
4567 *Progress = TmpPtr - 1;\r
4568 Status = EFI_INVALID_PARAMETER;\r
4569 goto Exit;\r
4570 }\r
4571\r
4572 //\r
4573 // Calculate Value and convert it to hex string.\r
4574 //\r
4575 if (Offset + Width > BlockSize) {\r
4576 *Progress = StringPtr;\r
4577 Status = EFI_DEVICE_ERROR;\r
4578 goto Exit;\r
4579 }\r
4580\r
4581 Value = (UINT8 *) AllocateZeroPool (Width);\r
4582 if (Value == NULL) {\r
4583 *Progress = ConfigRequest;\r
4584 Status = EFI_OUT_OF_RESOURCES;\r
4585 goto Exit;\r
4586 }\r
4587\r
4588 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
4589\r
4590 Length = Width * 2 + 1;\r
4591 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4592 if (ValueStr == NULL) {\r
4593 *Progress = ConfigRequest;\r
4594 Status = EFI_OUT_OF_RESOURCES;\r
4595 goto Exit;\r
4596 }\r
4597 \r
4598 TemString = ValueStr;\r
4599 TemBuffer = Value + Width - 1;\r
4600 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
4601 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
4602 }\r
4603\r
4604 FreePool (Value);\r
4605 Value = NULL;\r
4606\r
4607 //\r
4608 // Build a ConfigElement\r
4609 //\r
4610 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
4611 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
4612 if (ConfigElement == NULL) {\r
4613 Status = EFI_OUT_OF_RESOURCES;\r
4614 goto Exit;\r
4615 }\r
4616 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
4617 if (*StringPtr == 0) {\r
4618 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
4619 }\r
4620 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
4621 StrCatS (ConfigElement, Length, L"VALUE=");\r
4622 StrCatS (ConfigElement, Length, ValueStr);\r
4623\r
4624 AppendToMultiString (Config, ConfigElement);\r
4625\r
4626 FreePool (ConfigElement);\r
4627 FreePool (ValueStr);\r
4628 ConfigElement = NULL;\r
4629 ValueStr = NULL;\r
4630\r
4631 //\r
4632 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
4633 //\r
4634 if (*StringPtr == 0) {\r
4635 break;\r
4636 }\r
4637 AppendToMultiString (Config, L"&");\r
4638 StringPtr++;\r
4639\r
4640 }\r
4641\r
4642 if (*StringPtr != 0) {\r
4643 *Progress = StringPtr - 1;\r
4644 Status = EFI_INVALID_PARAMETER;\r
4645 goto Exit;\r
4646 }\r
4647 \r
4648 HiiToLower (*Config);\r
4649 *Progress = StringPtr;\r
4650 return EFI_SUCCESS;\r
4651\r
4652Exit:\r
4653 if (*Config != NULL) {\r
4654 FreePool (*Config);\r
4655 *Config = NULL;\r
4656 }\r
4657 if (ValueStr != NULL) {\r
4658 FreePool (ValueStr);\r
4659 }\r
4660 if (Value != NULL) {\r
4661 FreePool (Value);\r
4662 }\r
4663 if (ConfigElement != NULL) {\r
4664 FreePool (ConfigElement);\r
4665 }\r
4666\r
4667 return Status;\r
4668\r
4669}\r
4670\r
4671\r
4672/**\r
4673 This helper function is to be called by drivers to map configuration strings\r
4674 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
4675\r
4676 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4677 instance.\r
4678 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
4679 format.\r
4680 @param Block A possibly null array of bytes representing the\r
4681 current block. Only bytes referenced in the\r
4682 ConfigResp string in the block are modified. If\r
4683 this parameter is null or if the *BlockSize\r
4684 parameter is (on input) shorter than required by\r
4685 the Configuration string, only the BlockSize\r
4686 parameter is updated and an appropriate status\r
4687 (see below) is returned.\r
4688 @param BlockSize The length of the Block in units of UINT8. On\r
4689 input, this is the size of the Block. On output,\r
4690 if successful, contains the largest index of the\r
4691 modified byte in the Block, or the required buffer\r
4692 size if the Block is not large enough.\r
4693 @param Progress On return, points to an element of the ConfigResp\r
4694 string filled in with the offset of the most\r
4695 recent '&' before the first failing name / value\r
4696 pair (or the beginning of the string if the\r
4697 failure is in the first name / value pair) or the\r
4698 terminating NULL if all was successful.\r
4699\r
4700 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
4701 terminator at the end of the ConfigResp string.\r
4702 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
4703 points to the first character of ConfigResp.\r
4704 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
4705 Block parameter would result in this type of\r
4706 error. Progress points to the first character of\r
4707 ConfigResp.\r
4708 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
4709 value pair. Block is left updated and\r
4710 Progress points at the '&' preceding the first\r
4711 non-<BlockName>.\r
4712 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined. \r
4713 BlockSize is updated with the required buffer size.\r
4714 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
4715 Progress points to the "G" in "GUID" of the errant\r
4716 routing data.\r
4717\r
4718**/\r
4719EFI_STATUS\r
4720EFIAPI\r
4721HiiConfigToBlock (\r
4722 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4723 IN CONST EFI_STRING ConfigResp,\r
4724 IN OUT UINT8 *Block,\r
4725 IN OUT UINTN *BlockSize,\r
4726 OUT EFI_STRING *Progress\r
4727 )\r
4728{\r
4729 HII_DATABASE_PRIVATE_DATA *Private;\r
4730 EFI_STRING StringPtr;\r
4731 EFI_STRING TmpPtr;\r
4732 UINTN Length;\r
4733 EFI_STATUS Status;\r
4734 UINT8 *TmpBuffer;\r
4735 UINTN Offset;\r
4736 UINTN Width;\r
4737 UINT8 *Value;\r
4738 UINTN BufferSize;\r
4739 UINTN MaxBlockSize;\r
4740\r
4741 TmpBuffer = NULL;\r
4742\r
4743 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
4744 return EFI_INVALID_PARAMETER;\r
4745 }\r
4746\r
4747 *Progress = ConfigResp;\r
4748 if (ConfigResp == NULL) {\r
4749 return EFI_INVALID_PARAMETER;\r
4750 }\r
4751\r
4752 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4753 ASSERT (Private != NULL);\r
4754\r
4755 StringPtr = ConfigResp;\r
4756 BufferSize = *BlockSize;\r
4757 Value = NULL;\r
4758 MaxBlockSize = 0;\r
4759\r
4760 //\r
4761 // Jump <ConfigHdr>\r
4762 //\r
4763 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4764 *Progress = StringPtr;\r
4765 Status = EFI_INVALID_PARAMETER;\r
4766 goto Exit;\r
4767 }\r
4768 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
4769 StringPtr++;\r
4770 }\r
4771 if (*StringPtr == 0) {\r
4772 *Progress = StringPtr;\r
4773 Status = EFI_INVALID_PARAMETER;\r
4774 goto Exit;\r
4775 }\r
4776\r
4777 while (*StringPtr != L'&' && *StringPtr != 0) {\r
4778 StringPtr++;\r
4779 }\r
4780 if (*StringPtr == 0) {\r
4781 *Progress = StringPtr;\r
4782 Status = EFI_INVALID_PARAMETER;\r
4783 goto Exit;\r
4784 }\r
4785\r
4786 //\r
4787 // Parse each <ConfigElement> if exists\r
4788 // Only '&'<BlockConfig> format is supported by this help function.\r
4789 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
4790 //\r
4791 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
4792 TmpPtr = StringPtr;\r
4793 StringPtr += StrLen (L"&OFFSET=");\r
4794 //\r
4795 // Get Offset\r
4796 //\r
4797 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
4798 if (EFI_ERROR (Status)) {\r
4799 *Progress = TmpPtr;\r
4800 goto Exit;\r
4801 }\r
4802 Offset = 0;\r
4803 CopyMem (\r
4804 &Offset,\r
4805 TmpBuffer,\r
4806 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4807 );\r
4808 FreePool (TmpBuffer);\r
4809\r
4810 StringPtr += Length;\r
4811 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4812 *Progress = TmpPtr;\r
4813 Status = EFI_INVALID_PARAMETER;\r
4814 goto Exit;\r
4815 }\r
4816 StringPtr += StrLen (L"&WIDTH=");\r
4817\r
4818 //\r
4819 // Get Width\r
4820 //\r
4821 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
4822 if (EFI_ERROR (Status)) {\r
4823 *Progress = TmpPtr;\r
4824 goto Exit;\r
4825 }\r
4826 Width = 0;\r
4827 CopyMem (\r
4828 &Width,\r
4829 TmpBuffer,\r
4830 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
4831 );\r
4832 FreePool (TmpBuffer);\r
4833\r
4834 StringPtr += Length;\r
4835 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
4836 *Progress = TmpPtr;\r
4837 Status = EFI_INVALID_PARAMETER;\r
4838 goto Exit;\r
4839 }\r
4840 StringPtr += StrLen (L"&VALUE=");\r
4841\r
4842 //\r
4843 // Get Value\r
4844 //\r
4845 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
4846 if (EFI_ERROR (Status)) {\r
4847 *Progress = TmpPtr;\r
4848 goto Exit;\r
4849 }\r
4850\r
4851 StringPtr += Length;\r
4852 if (*StringPtr != 0 && *StringPtr != L'&') {\r
4853 *Progress = TmpPtr;\r
4854 Status = EFI_INVALID_PARAMETER;\r
4855 goto Exit;\r
4856 }\r
4857\r
4858 //\r
4859 // Update the Block with configuration info\r
4860 //\r
4861 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
4862 CopyMem (Block + Offset, Value, Width);\r
4863 }\r
4864 if (Offset + Width > MaxBlockSize) {\r
4865 MaxBlockSize = Offset + Width;\r
4866 }\r
4867\r
4868 FreePool (Value);\r
4869 Value = NULL;\r
4870\r
4871 //\r
4872 // If '\0', parsing is finished.\r
4873 //\r
4874 if (*StringPtr == 0) {\r
4875 break;\r
4876 }\r
4877 }\r
4878 \r
4879 //\r
4880 // The input string is not ConfigResp format, return error.\r
4881 //\r
4882 if (*StringPtr != 0) {\r
4883 *Progress = StringPtr;\r
4884 Status = EFI_INVALID_PARAMETER;\r
4885 goto Exit;\r
4886 }\r
4887\r
4888 *Progress = StringPtr + StrLen (StringPtr);\r
4889 *BlockSize = MaxBlockSize - 1;\r
4890\r
4891 if (MaxBlockSize > BufferSize) {\r
4892 *BlockSize = MaxBlockSize;\r
4893 if (Block != NULL) {\r
4894 return EFI_BUFFER_TOO_SMALL;\r
4895 }\r
4896 }\r
4897\r
4898 if (Block == NULL) {\r
4899 *Progress = ConfigResp;\r
4900 return EFI_INVALID_PARAMETER;\r
4901 }\r
4902\r
4903 return EFI_SUCCESS;\r
4904\r
4905Exit:\r
4906\r
4907 if (Value != NULL) {\r
4908 FreePool (Value);\r
4909 }\r
4910 return Status;\r
4911}\r
4912\r
4913\r
4914/**\r
4915 This helper function is to be called by drivers to extract portions of\r
4916 a larger configuration string.\r
4917\r
4918 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4919 instance.\r
4920 @param Configuration A null-terminated Unicode string in\r
4921 <MultiConfigAltResp> format.\r
4922 @param Guid A pointer to the GUID value to search for in the\r
4923 routing portion of the ConfigResp string when\r
4924 retrieving the requested data. If Guid is NULL,\r
4925 then all GUID values will be searched for.\r
4926 @param Name A pointer to the NAME value to search for in the\r
4927 routing portion of the ConfigResp string when\r
4928 retrieving the requested data. If Name is NULL,\r
4929 then all Name values will be searched for.\r
4930 @param DevicePath A pointer to the PATH value to search for in the\r
4931 routing portion of the ConfigResp string when\r
4932 retrieving the requested data. If DevicePath is\r
4933 NULL, then all DevicePath values will be searched\r
4934 for.\r
4935 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
4936 routing portion of the ConfigResp string when\r
4937 retrieving the requested data. If this parameter\r
4938 is NULL, then the current setting will be\r
4939 retrieved.\r
4940 @param AltCfgResp A pointer to a buffer which will be allocated by\r
4941 the function which contains the retrieved string\r
4942 as requested. This buffer is only allocated if\r
4943 the call was successful. It is <ConfigResp> format.\r
4944\r
4945 @retval EFI_SUCCESS The request succeeded. The requested data was\r
4946 extracted and placed in the newly allocated\r
4947 AltCfgResp buffer.\r
4948 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
4949 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
4950 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
4951 found.\r
4952\r
4953**/\r
4954EFI_STATUS\r
4955EFIAPI\r
4956HiiGetAltCfg (\r
4957 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4958 IN CONST EFI_STRING Configuration,\r
4959 IN CONST EFI_GUID *Guid,\r
4960 IN CONST EFI_STRING Name,\r
4961 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4962 IN CONST UINT16 *AltCfgId,\r
4963 OUT EFI_STRING *AltCfgResp\r
4964 )\r
4965{\r
4966 EFI_STATUS Status;\r
4967 EFI_STRING StringPtr;\r
4968 EFI_STRING HdrStart;\r
4969 EFI_STRING HdrEnd;\r
4970 EFI_STRING TmpPtr;\r
4971 UINTN Length;\r
4972 EFI_STRING GuidStr;\r
4973 EFI_STRING NameStr;\r
4974 EFI_STRING PathStr;\r
4975 EFI_STRING AltIdStr;\r
4976 EFI_STRING Result;\r
4977 BOOLEAN GuidFlag;\r
4978 BOOLEAN NameFlag;\r
4979 BOOLEAN PathFlag;\r
4980\r
4981 HdrStart = NULL;\r
4982 HdrEnd = NULL;\r
4983 GuidStr = NULL;\r
4984 NameStr = NULL;\r
4985 PathStr = NULL;\r
4986 AltIdStr = NULL;\r
4987 Result = NULL;\r
4988 GuidFlag = FALSE;\r
4989 NameFlag = FALSE;\r
4990 PathFlag = FALSE;\r
4991\r
4992 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
4993 return EFI_INVALID_PARAMETER;\r
4994 }\r
4995\r
4996 StringPtr = Configuration;\r
4997 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4998 return EFI_INVALID_PARAMETER;\r
4999 }\r
5000\r
5001 //\r
5002 // Generate the sub string for later matching.\r
5003 //\r
5004 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
5005 GenerateSubStr (\r
5006 L"PATH=",\r
5007 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
5008 (VOID *) DevicePath,\r
5009 1,\r
5010 &PathStr\r
5011 );\r
5012 if (AltCfgId != NULL) {\r
5013 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
5014 }\r
5015 if (Name != NULL) {\r
5016 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
5017 } else {\r
5018 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
5019 }\r
5020\r
5021 while (*StringPtr != 0) {\r
5022 //\r
5023 // Try to match the GUID\r
5024 //\r
5025 if (!GuidFlag) {\r
5026 TmpPtr = StrStr (StringPtr, GuidStr);\r
5027 if (TmpPtr == NULL) {\r
5028 Status = EFI_NOT_FOUND;\r
5029 goto Exit;\r
5030 }\r
5031 HdrStart = TmpPtr;\r
5032\r
5033 //\r
5034 // Jump to <NameHdr>\r
5035 //\r
5036 if (Guid != NULL) {\r
5037 StringPtr = TmpPtr + StrLen (GuidStr);\r
5038 } else {\r
5039 StringPtr = StrStr (TmpPtr, L"NAME=");\r
5040 if (StringPtr == NULL) {\r
5041 Status = EFI_NOT_FOUND;\r
5042 goto Exit;\r
5043 }\r
5044 }\r
5045 GuidFlag = TRUE;\r
5046 }\r
5047\r
5048 //\r
5049 // Try to match the NAME\r
5050 //\r
5051 if (GuidFlag && !NameFlag) {\r
5052 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
5053 GuidFlag = FALSE;\r
5054 } else {\r
5055 //\r
5056 // Jump to <PathHdr>\r
5057 //\r
5058 if (Name != NULL) {\r
5059 StringPtr += StrLen (NameStr);\r
5060 } else {\r
5061 StringPtr = StrStr (StringPtr, L"PATH=");\r
5062 if (StringPtr == NULL) {\r
5063 Status = EFI_NOT_FOUND;\r
5064 goto Exit;\r
5065 }\r
5066 }\r
5067 NameFlag = TRUE;\r
5068 }\r
5069 }\r
5070\r
5071 //\r
5072 // Try to match the DevicePath\r
5073 //\r
5074 if (GuidFlag && NameFlag && !PathFlag) {\r
5075 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
5076 GuidFlag = FALSE;\r
5077 NameFlag = FALSE;\r
5078 } else {\r
5079 //\r
5080 // Jump to '&' before <DescHdr> or <ConfigBody>\r
5081 //\r
5082 if (DevicePath != NULL) {\r
5083 StringPtr += StrLen (PathStr);\r
5084 } else {\r
5085 StringPtr = StrStr (StringPtr, L"&");\r
5086 if (StringPtr == NULL) {\r
5087 Status = EFI_NOT_FOUND;\r
5088 goto Exit;\r
5089 }\r
5090 StringPtr ++;\r
5091 }\r
5092 PathFlag = TRUE;\r
5093 HdrEnd = StringPtr;\r
5094 }\r
5095 }\r
5096\r
5097 //\r
5098 // Try to match the AltCfgId\r
5099 //\r
5100 if (GuidFlag && NameFlag && PathFlag) {\r
5101 if (AltCfgId == NULL) {\r
5102 //\r
5103 // Return Current Setting when AltCfgId is NULL.\r
5104 //\r
5105 Status = OutputConfigBody (StringPtr, &Result);\r
5106 goto Exit;\r
5107 }\r
5108 //\r
5109 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
5110 //\r
5111 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
5112 GuidFlag = FALSE;\r
5113 NameFlag = FALSE;\r
5114 PathFlag = FALSE;\r
5115 } else {\r
5116 //\r
5117 // Skip AltIdStr and &\r
5118 //\r
5119 StringPtr = StringPtr + StrLen (AltIdStr);\r
5120 Status = OutputConfigBody (StringPtr, &Result);\r
5121 goto Exit;\r
5122 }\r
5123 }\r
5124 }\r
5125\r
5126 Status = EFI_NOT_FOUND;\r
5127\r
5128Exit:\r
5129 *AltCfgResp = NULL;\r
5130 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
5131 //\r
5132 // Copy the <ConfigHdr> and <ConfigBody>\r
5133 //\r
5134 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
5135 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
5136 if (*AltCfgResp == NULL) {\r
5137 Status = EFI_OUT_OF_RESOURCES;\r
5138 } else {\r
5139 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);\r
5140 StrCatS (*AltCfgResp, Length, Result);\r
5141 Status = EFI_SUCCESS;\r
5142 }\r
5143 }\r
5144\r
5145 if (GuidStr != NULL) {\r
5146 FreePool (GuidStr);\r
5147 }\r
5148 if (NameStr != NULL) {\r
5149 FreePool (NameStr);\r
5150 }\r
5151 if (PathStr != NULL) {\r
5152 FreePool (PathStr);\r
5153 }\r
5154 if (AltIdStr != NULL) {\r
5155 FreePool (AltIdStr);\r
5156 }\r
5157 if (Result != NULL) {\r
5158 FreePool (Result);\r
5159 }\r
5160\r
5161 return Status;\r
5162\r
5163}\r
5164\r
5165\r