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