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