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