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