]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg HiiDataBase: Fix the potential NULL pointer reference
[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
37cd16ac 1228 if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && BlockArray->Width == BlockSingleData->Width)) {\r
84f9a9ec
LG
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
37cd16ac 1236 if ((!BlockSingleData->IsBitVar) && BlockArray->Width == BlockSingleData->Width) {\r
84f9a9ec
LG
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
37cd16ac 1983 @param IsBitVar Whether the the opcode refers to bit storage.\r
82e8c138
ED
1984\r
1985 @retval EFI_SUCCESS This opcode is required.\r
f447734e
DB
1986 @retval EFI_NOT_FOUND This opcode is not required.\r
1987 @retval Others Contain some error.\r
82e8c138
ED
1988 \r
1989**/\r
1990EFI_STATUS\r
1991IsThisOpcodeRequired (\r
1992 IN IFR_BLOCK_DATA *RequestBlockArray,\r
1993 IN EFI_HII_HANDLE HiiHandle,\r
1994 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
1995 IN EFI_IFR_OP_HEADER *IfrOpHdr,\r
1996 IN UINT16 VarWidth,\r
37cd16ac
DB
1997 OUT IFR_BLOCK_DATA **ReturnData,\r
1998 IN BOOLEAN IsBitVar\r
82e8c138
ED
1999 )\r
2000{\r
2001 IFR_BLOCK_DATA *BlockData;\r
2002 UINT16 VarOffset;\r
2003 EFI_STRING_ID NameId;\r
2004 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
37cd16ac
DB
2005 UINT16 BitOffset;\r
2006 UINT16 BitWidth;\r
2007 UINT16 TotalBits;\r
82e8c138
ED
2008\r
2009 NameId = 0;\r
2010 VarOffset = 0;\r
37cd16ac
DB
2011 BitOffset = 0;\r
2012 BitWidth = 0;\r
82e8c138
ED
2013 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));\r
2014\r
2015 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2016 NameId = IfrQuestionHdr->VarStoreInfo.VarName;\r
2017\r
2018 //\r
2019 // Check whether this question is in requested block array.\r
2020 //\r
2021 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {\r
2022 //\r
2023 // This question is not in the requested string. Skip it.\r
2024 //\r
f447734e 2025 return EFI_NOT_FOUND;\r
82e8c138
ED
2026 }\r
2027 } else {\r
37cd16ac
DB
2028 //\r
2029 // Get the byte offset/with and bit offset/width\r
2030 //\r
2031 if (IsBitVar) {\r
2032 BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
2033 BitWidth = VarWidth;\r
2034 VarOffset = BitOffset / 8;\r
2035 //\r
2036 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.\r
2037 //\r
2038 TotalBits = BitOffset % 8 + BitWidth;\r
2039 VarWidth = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
2040 } else {\r
2041 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
2042 BitWidth = VarWidth;\r
2043 BitOffset = VarOffset * 8;\r
2044 }\r
82e8c138
ED
2045 \r
2046 //\r
2047 // Check whether this question is in requested block array.\r
2048 //\r
2049 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {\r
2050 //\r
2051 // This question is not in the requested string. Skip it.\r
2052 //\r
f447734e 2053 return EFI_NOT_FOUND;\r
82e8c138
ED
2054 }\r
2055\r
2056 //\r
2057 // Check this var question is in the var storage \r
2058 //\r
2059 if (((VarOffset + VarWidth) > VarStorageData->Size)) {\r
2060 return EFI_INVALID_PARAMETER;\r
2061 }\r
2062 }\r
2063\r
2064 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
2065 if (BlockData == NULL) {\r
2066 return EFI_OUT_OF_RESOURCES;\r
2067 }\r
2068\r
2069 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2070 BlockData->Name = InternalGetString(HiiHandle, NameId);\r
2071 } else {\r
2072 BlockData->Offset = VarOffset;\r
2073 }\r
2074\r
2075 BlockData->Width = VarWidth;\r
2076 BlockData->QuestionId = IfrQuestionHdr->QuestionId;\r
2077 BlockData->OpCode = IfrOpHdr->OpCode;\r
2078 BlockData->Scope = IfrOpHdr->Scope;\r
37cd16ac
DB
2079 BlockData->IsBitVar = IsBitVar;\r
2080 BlockData->BitOffset = BitOffset;\r
2081 BlockData->BitWidth = BitWidth;\r
82e8c138
ED
2082 InitializeListHead (&BlockData->DefaultValueEntry);\r
2083 //\r
2084 // Add Block Data into VarStorageData BlockEntry\r
2085 //\r
2086 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
2087 *ReturnData = BlockData;\r
2088\r
2089 return EFI_SUCCESS;\r
2090}\r
2091\r
84f9a9ec
LG
2092/**\r
2093 This function parses Form Package to get the block array and the default\r
2094 value array according to the request ConfigHdr.\r
2095\r
82e8c138 2096 @param HiiHandle Hii Handle for this hii package.\r
84f9a9ec 2097 @param Package Pointer to the form package data.\r
4a429716 2098 @param PackageLength Length of the package.\r
84f9a9ec
LG
2099 @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
2100 the first found varstore will be as ConfigHdr.\r
2101 @param RequestBlockArray The block array is retrieved from the request string.\r
2102 @param VarStorageData VarStorage structure contains the got block and default value.\r
82e8c138 2103 @param DefaultIdArray Point to the got default id and default name array.\r
84f9a9ec
LG
2104\r
2105 @retval EFI_SUCCESS The block array and the default value array are got.\r
4a429716 2106 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages\r
84f9a9ec
LG
2107 are conflicted. \r
2108 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
2109**/\r
2110EFI_STATUS\r
2111EFIAPI\r
2112ParseIfrData (\r
82e8c138 2113 IN EFI_HII_HANDLE HiiHandle,\r
84f9a9ec 2114 IN UINT8 *Package,\r
aa75dfec 2115 IN UINT32 PackageLength,\r
84f9a9ec
LG
2116 IN EFI_STRING ConfigHdr,\r
2117 IN IFR_BLOCK_DATA *RequestBlockArray,\r
2118 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
8567300a 2119 OUT IFR_DEFAULT_DATA *DefaultIdArray\r
84f9a9ec
LG
2120 )\r
2121{\r
2122 EFI_STATUS Status;\r
2123 UINTN IfrOffset;\r
22031c4f 2124 UINTN PackageOffset;\r
84f9a9ec 2125 EFI_IFR_VARSTORE *IfrVarStore;\r
cce6230f 2126 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
84f9a9ec
LG
2127 EFI_IFR_OP_HEADER *IfrOpHdr;\r
2128 EFI_IFR_ONE_OF *IfrOneOf;\r
e7fd76d1 2129 EFI_IFR_REF4 *IfrRef;\r
84f9a9ec
LG
2130 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
2131 EFI_IFR_DEFAULT *IfrDefault;\r
2132 EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
2133 EFI_IFR_CHECKBOX *IfrCheckBox;\r
2134 EFI_IFR_PASSWORD *IfrPassword;\r
2135 EFI_IFR_STRING *IfrString;\r
d9bbabfd
ED
2136 EFI_IFR_DATE *IfrDate;\r
2137 EFI_IFR_TIME *IfrTime;\r
ef40f0f6
ED
2138 IFR_DEFAULT_DATA DefaultData;\r
2139 IFR_DEFAULT_DATA *DefaultDataPtr;\r
84f9a9ec 2140 IFR_BLOCK_DATA *BlockData;\r
40ae09a2 2141 CHAR16 *VarStoreName;\r
b68ccac1 2142 UINTN NameSize;\r
40ae09a2
ED
2143 UINT16 VarWidth;\r
2144 UINT16 VarDefaultId;\r
40ae09a2 2145 BOOLEAN FirstOneOfOption;\r
9495c01e 2146 BOOLEAN FirstOrderedList;\r
40ae09a2
ED
2147 LIST_ENTRY *LinkData;\r
2148 LIST_ENTRY *LinkDefault;\r
2149 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
22031c4f
ED
2150 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
2151 EFI_VARSTORE_ID VarStoreId;\r
22f63ff6 2152 UINT16 SmallestDefaultId;\r
0cdde071 2153 BOOLEAN SmallestIdFromFlag;\r
22f63ff6 2154 BOOLEAN FromOtherDefaultOpcode;\r
37cd16ac 2155 BOOLEAN QuestionReferBitField;\r
40ae09a2 2156\r
40ae09a2 2157 Status = EFI_SUCCESS;\r
40ae09a2
ED
2158 BlockData = NULL;\r
2159 DefaultDataPtr = NULL;\r
2160 FirstOneOfOption = FALSE;\r
22031c4f 2161 VarStoreId = 0;\r
9495c01e 2162 FirstOrderedList = FALSE;\r
a0b0cd73 2163 VarStoreName = NULL;\r
ef40f0f6 2164 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
22f63ff6
DB
2165 SmallestDefaultId = 0xFFFF;\r
2166 FromOtherDefaultOpcode = FALSE;\r
37cd16ac 2167 QuestionReferBitField = FALSE;\r
84f9a9ec
LG
2168\r
2169 //\r
2170 // Go through the form package to parse OpCode one by one.\r
2171 //\r
22031c4f
ED
2172 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
2173 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;\r
2174 IfrOffset = PackageOffset;\r
aa75dfec 2175 while (IfrOffset < PackageLength) {\r
22031c4f
ED
2176\r
2177 //\r
2178 // More than one form package found.\r
2179 //\r
2180 if (PackageOffset >= PackageHeader->Length) {\r
2181 //\r
2182 // Already found varstore for this request, break;\r
2183 //\r
2184 if (VarStoreId != 0) {\r
2185 VarStoreId = 0;\r
2186 }\r
2187\r
2188 //\r
2189 // Get next package header info.\r
2190 //\r
2191 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);\r
2192 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
2193 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);\r
2194 }\r
2195\r
84f9a9ec 2196 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
84f9a9ec
LG
2197 switch (IfrOpHdr->OpCode) {\r
2198 case EFI_IFR_VARSTORE_OP:\r
2199 //\r
2200 // VarStore is found. Don't need to search any more.\r
2201 //\r
22031c4f 2202 if (VarStoreId != 0) {\r
84f9a9ec
LG
2203 break;\r
2204 }\r
2205\r
84f9a9ec 2206 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
82e8c138 2207\r
b68ccac1
SZ
2208 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);\r
2209 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
84f9a9ec
LG
2210 if (VarStoreName == NULL) {\r
2211 Status = EFI_OUT_OF_RESOURCES;\r
2212 goto Done;\r
2213 }\r
b68ccac1 2214 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);\r
84f9a9ec 2215\r
82e8c138 2216 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
84f9a9ec
LG
2217 //\r
2218 // Find the matched VarStore\r
2219 //\r
2220 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
84f9a9ec
LG
2221 VarStorageData->Size = IfrVarStore->Size;\r
2222 VarStorageData->Name = VarStoreName;\r
82e8c138 2223 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
22031c4f 2224 VarStoreId = IfrVarStore->VarStoreId;\r
a0b0cd73
DB
2225 } else {\r
2226 FreePool (VarStoreName);\r
2227 VarStoreName = NULL;\r
84f9a9ec 2228 }\r
84f9a9ec
LG
2229 break;\r
2230\r
cce6230f
ED
2231 case EFI_IFR_VARSTORE_EFI_OP:\r
2232 //\r
2233 // VarStore is found. Don't need to search any more.\r
2234 //\r
22031c4f 2235 if (VarStoreId != 0) {\r
cce6230f
ED
2236 break;\r
2237 }\r
2238\r
cce6230f
ED
2239 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
2240\r
2241 //\r
2242 // If the length is small than the structure, this is from old efi \r
2243 // varstore definition. Old efi varstore get config directly from \r
2244 // GetVariable function.\r
2245 // \r
2246 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
2247 break;\r
2248 }\r
2249\r
b68ccac1
SZ
2250 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);\r
2251 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
cce6230f
ED
2252 if (VarStoreName == NULL) {\r
2253 Status = EFI_OUT_OF_RESOURCES;\r
2254 goto Done;\r
2255 }\r
b68ccac1 2256 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);\r
cce6230f 2257\r
82e8c138 2258 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
cce6230f
ED
2259 //\r
2260 // Find the matched VarStore\r
2261 //\r
2262 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);\r
cce6230f
ED
2263 VarStorageData->Size = IfrEfiVarStore->Size;\r
2264 VarStorageData->Name = VarStoreName;\r
82e8c138 2265 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
22031c4f 2266 VarStoreId = IfrEfiVarStore->VarStoreId;\r
a0b0cd73
DB
2267 } else {\r
2268 FreePool (VarStoreName);\r
2269 VarStoreName = NULL;\r
cce6230f 2270 }\r
cce6230f
ED
2271 break;\r
2272\r
82e8c138 2273 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
84f9a9ec 2274 //\r
82e8c138
ED
2275 // VarStore is found. Don't need to search any more.\r
2276 //\r
22031c4f 2277 if (VarStoreId != 0) {\r
82e8c138
ED
2278 break;\r
2279 }\r
2280\r
2281 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
2282\r
2283 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
2284 //\r
2285 // Find the matched VarStore\r
2286 //\r
2287 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);\r
82e8c138 2288 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
22031c4f 2289 VarStoreId = IfrNameValueVarStore->VarStoreId;\r
82e8c138
ED
2290 }\r
2291 break;\r
2292\r
2293 case EFI_IFR_DEFAULTSTORE_OP:\r
2294 //\r
2295 // Add new the map between default id and default name.\r
84f9a9ec 2296 //\r
ef40f0f6
ED
2297 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
2298 if (DefaultDataPtr == NULL) {\r
84f9a9ec
LG
2299 Status = EFI_OUT_OF_RESOURCES;\r
2300 goto Done;\r
2301 }\r
ef40f0f6
ED
2302 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
2303 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
2304 DefaultDataPtr = NULL;\r
84f9a9ec
LG
2305 break;\r
2306\r
2307 case EFI_IFR_FORM_OP:\r
2573712e 2308 case EFI_IFR_FORM_MAP_OP:\r
84f9a9ec
LG
2309 //\r
2310 // No matched varstore is found and directly return.\r
2311 //\r
22031c4f 2312 if ( VarStoreId == 0) {\r
84f9a9ec
LG
2313 Status = EFI_SUCCESS;\r
2314 goto Done;\r
2315 }\r
2316 break;\r
2317\r
e7fd76d1
ED
2318 case EFI_IFR_REF_OP:\r
2319 //\r
2320 // Ref question is not in IFR Form. This IFR form is not valid. \r
2321 //\r
22031c4f 2322 if ( VarStoreId == 0) {\r
e7fd76d1
ED
2323 Status = EFI_INVALID_PARAMETER;\r
2324 goto Done;\r
2325 }\r
2326 //\r
2327 // Check whether this question is for the requested varstore.\r
2328 //\r
2329 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;\r
22031c4f 2330 if (IfrRef->Question.VarStoreId != VarStoreId) {\r
e7fd76d1
ED
2331 break;\r
2332 }\r
e7fd76d1 2333 VarWidth = (UINT16) (sizeof (EFI_HII_REF));\r
e7fd76d1 2334\r
f447734e
DB
2335 //\r
2336 // The BlockData may allocate by other opcode,need to clean.\r
2337 //\r
2338 if (BlockData != NULL){\r
2339 BlockData = NULL;\r
2340 }\r
2341\r
37cd16ac 2342 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2343 if (EFI_ERROR (Status)) {\r
f447734e
DB
2344 if (Status == EFI_NOT_FOUND){\r
2345 //\r
2346 //The opcode is not required,exit and parse other opcode.\r
2347 //\r
2348 break;\r
2349 }\r
e7fd76d1
ED
2350 goto Done;\r
2351 }\r
e7fd76d1
ED
2352 break;\r
2353\r
84f9a9ec
LG
2354 case EFI_IFR_ONE_OF_OP:\r
2355 case EFI_IFR_NUMERIC_OP:\r
2356 //\r
2357 // Numeric and OneOf has the same opcode structure.\r
2358 //\r
2359\r
8567300a
LG
2360 //\r
2361 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
2362 //\r
22031c4f 2363 if (VarStoreId == 0) {\r
8567300a
LG
2364 Status = EFI_INVALID_PARAMETER;\r
2365 goto Done;\r
2366 }\r
84f9a9ec
LG
2367 //\r
2368 // Check whether this question is for the requested varstore.\r
2369 //\r
2370 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
22031c4f 2371 if (IfrOneOf->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2372 break;\r
2373 }\r
37cd16ac
DB
2374\r
2375 if (QuestionReferBitField) {\r
2376 VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
2377 } else {\r
2378 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
2379 }\r
84f9a9ec 2380\r
f447734e
DB
2381 //\r
2382 // The BlockData may allocate by other opcode,need to clean.\r
2383 //\r
2384 if (BlockData != NULL){\r
2385 BlockData = NULL;\r
2386 }\r
2387\r
37cd16ac 2388 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
82e8c138 2389 if (EFI_ERROR (Status)) {\r
f447734e
DB
2390 if (Status == EFI_NOT_FOUND){\r
2391 //\r
2392 //The opcode is not required,exit and parse other opcode.\r
2393 //\r
2394 break;\r
2395 }\r
84f9a9ec
LG
2396 goto Done;\r
2397 }\r
82e8c138 2398\r
f447734e
DB
2399 //\r
2400 //when go to there,BlockData can't be NULLL.\r
2401 //\r
2402 ASSERT (BlockData != NULL);\r
82e8c138 2403\r
cf4c5a42
LG
2404 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
2405 //\r
2406 // Set this flag to TRUE for the first oneof option.\r
2407 //\r
2408 FirstOneOfOption = TRUE;\r
2409 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
2410 //\r
2411 // Numeric minimum value will be used as default value when no default is specified. \r
2412 //\r
eb5e7d3e 2413 DefaultData.Type = DefaultValueFromDefault;\r
37cd16ac
DB
2414 if (QuestionReferBitField) {\r
2415 //\r
2416 // Since default value in bit field was stored as UINT32 type.\r
2417 //\r
e7fd76d1 2418 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
37cd16ac
DB
2419 } else {\r
2420 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
2421 case EFI_IFR_NUMERIC_SIZE_1:\r
2422 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
2423 break;\r
2424\r
2425 case EFI_IFR_NUMERIC_SIZE_2:\r
2426 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
2427 break;\r
2428\r
2429 case EFI_IFR_NUMERIC_SIZE_4:\r
2430 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
2431 break;\r
2432\r
2433 case EFI_IFR_NUMERIC_SIZE_8:\r
2434 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
2435 break;\r
2436\r
2437 default:\r
2438 Status = EFI_INVALID_PARAMETER;\r
2439 goto Done;\r
2440 }\r
cf4c5a42
LG
2441 }\r
2442 //\r
ef40f0f6
ED
2443 // Set default value base on the DefaultId list get from IFR data.\r
2444 // \r
2445 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
82e8c138 2446 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
ef40f0f6
ED
2447 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2448 InsertDefaultValue (BlockData, &DefaultData);\r
2449 }\r
cf4c5a42 2450 }\r
84f9a9ec
LG
2451 break;\r
2452\r
2453 case EFI_IFR_ORDERED_LIST_OP:\r
2454 //\r
2455 // offset by question header\r
2456 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
84f9a9ec 2457 //\r
8567300a 2458\r
9495c01e 2459 FirstOrderedList = TRUE;\r
8567300a
LG
2460 //\r
2461 // OrderedList question is not in IFR Form. This IFR form is not valid. \r
2462 //\r
22031c4f 2463 if (VarStoreId == 0) {\r
8567300a
LG
2464 Status = EFI_INVALID_PARAMETER;\r
2465 goto Done;\r
2466 }\r
84f9a9ec
LG
2467 //\r
2468 // Check whether this question is for the requested varstore.\r
2469 //\r
2470 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
22031c4f 2471 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {\r
ff28420b 2472 BlockData = NULL;\r
84f9a9ec
LG
2473 break;\r
2474 }\r
84f9a9ec 2475 VarWidth = IfrOrderedList->MaxContainers;\r
f447734e
DB
2476\r
2477 //\r
2478 // The BlockData may allocate by other opcode,need to clean.\r
2479 //\r
2480 if (BlockData != NULL){\r
2481 BlockData = NULL;\r
2482 }\r
2483\r
37cd16ac 2484 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2485 if (EFI_ERROR (Status)) {\r
f447734e
DB
2486 if (Status == EFI_NOT_FOUND){\r
2487 //\r
2488 //The opcode is not required,exit and parse other opcode.\r
2489 //\r
2490 break;\r
2491 }\r
84f9a9ec
LG
2492 goto Done;\r
2493 }\r
84f9a9ec
LG
2494 break;\r
2495\r
2496 case EFI_IFR_CHECKBOX_OP:\r
2497 //\r
2498 // EFI_IFR_DEFAULT_OP\r
2499 // offset by question header\r
2500 // width is 1 sizeof (BOOLEAN)\r
2501 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
2502 // value by DefaultOption\r
2503 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
2504 // \r
2505\r
8567300a
LG
2506 //\r
2507 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
2508 //\r
22031c4f 2509 if (VarStoreId == 0) {\r
8567300a
LG
2510 Status = EFI_INVALID_PARAMETER;\r
2511 goto Done;\r
2512 }\r
84f9a9ec
LG
2513 //\r
2514 // Check whether this question is for the requested varstore.\r
2515 //\r
2516 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
22031c4f 2517 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2518 break;\r
2519 }\r
c9325700 2520 VarWidth = (UINT16) sizeof (BOOLEAN);\r
f447734e
DB
2521\r
2522 //\r
2523 // The BlockData may allocate by other opcode,need to clean.\r
2524 //\r
2525 if (BlockData != NULL){\r
2526 BlockData = NULL;\r
2527 }\r
2528\r
37cd16ac
DB
2529 if (QuestionReferBitField) {\r
2530 VarWidth = 1;\r
2531 }\r
2532 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
82e8c138 2533 if (EFI_ERROR (Status)) {\r
f447734e
DB
2534 if (Status == EFI_NOT_FOUND){\r
2535 //\r
2536 //The opcode is not required,exit and parse other opcode.\r
2537 //\r
2538 break;\r
2539 }\r
82e8c138
ED
2540 goto Done;\r
2541 }\r
84f9a9ec 2542\r
f447734e
DB
2543 //\r
2544 //when go to there,BlockData can't be NULLL.\r
2545 //\r
2546 ASSERT (BlockData != NULL);\r
84f9a9ec 2547\r
22f63ff6
DB
2548 SmallestIdFromFlag = FALSE;\r
2549\r
84f9a9ec 2550 //\r
e9668a60 2551 // Add default value for standard ID by CheckBox Flag\r
84f9a9ec 2552 //\r
e9668a60
LG
2553 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2554 //\r
2555 // Prepare new DefaultValue\r
2556 //\r
ef40f0f6 2557 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
2558 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
2559 //\r
4a429716 2560 // When flag is set, default value is TRUE.\r
84f9a9ec 2561 //\r
e7fd76d1 2562 DefaultData.Type = DefaultValueFromFlag;\r
37cd16ac
DB
2563 if (QuestionReferBitField) {\r
2564 DefaultData.Value.u32 = TRUE;\r
2565 } else {\r
2566 DefaultData.Value.b = TRUE;\r
2567 }\r
22f63ff6
DB
2568 InsertDefaultValue (BlockData, &DefaultData);\r
2569\r
2570 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2571 //\r
2572 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2573 //\r
2574 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2575 SmallestIdFromFlag = TRUE;\r
2576 }\r
84f9a9ec
LG
2577 }\r
2578\r
e9668a60
LG
2579 //\r
2580 // Add default value for Manufacture ID by CheckBox Flag\r
2581 //\r
2582 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2583 //\r
2584 // Prepare new DefaultValue\r
2585 //\r
ef40f0f6 2586 DefaultData.DefaultId = VarDefaultId;\r
84f9a9ec
LG
2587 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
2588 //\r
4a429716 2589 // When flag is set, default value is TRUE.\r
84f9a9ec 2590 //\r
e7fd76d1 2591 DefaultData.Type = DefaultValueFromFlag;\r
37cd16ac
DB
2592 if (QuestionReferBitField) {\r
2593 DefaultData.Value.u32 = TRUE;\r
2594 } else {\r
2595 DefaultData.Value.b = TRUE;\r
2596 }\r
22f63ff6
DB
2597 InsertDefaultValue (BlockData, &DefaultData);\r
2598\r
2599 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2600 //\r
2601 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2602 //\r
2603 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2604 SmallestIdFromFlag = TRUE;\r
2605 }\r
2606 }\r
2607 if (SmallestIdFromFlag) {\r
2608 //\r
4a429716 2609 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.\r
22f63ff6
DB
2610 //\r
2611 DefaultData.Type = DefaultValueFromOtherDefault;\r
37cd16ac
DB
2612 if (QuestionReferBitField) {\r
2613 DefaultData.Value.u32 = TRUE;\r
2614 } else {\r
2615 DefaultData.Value.b = TRUE;\r
2616 }\r
22f63ff6
DB
2617 //\r
2618 // Set default value for all the default id in the DefaultId list.\r
2619 //\r
2620 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2621 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2622 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2623 InsertDefaultValue (BlockData, &DefaultData);\r
2624 }\r
e9668a60 2625 } else {\r
84f9a9ec 2626 //\r
4a429716 2627 // When flag is not set, default value is FASLE.\r
84f9a9ec 2628 //\r
82e8c138 2629 DefaultData.Type = DefaultValueFromDefault;\r
37cd16ac
DB
2630 if (QuestionReferBitField) {\r
2631 DefaultData.Value.u32 = FALSE;\r
2632 } else {\r
2633 DefaultData.Value.b = FALSE;\r
2634 }\r
22f63ff6
DB
2635 //\r
2636 // Set default value for all the default id in the DefaultId list.\r
2637 //\r
2638 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2639 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2640 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2641 InsertDefaultValue (BlockData, &DefaultData);\r
2642 }\r
84f9a9ec
LG
2643 }\r
2644 break;\r
2645\r
d9bbabfd
ED
2646 case EFI_IFR_DATE_OP:\r
2647 //\r
2648 // offset by question header\r
2649 // width MaxSize * sizeof (CHAR16)\r
2650 // no default value, only block array\r
2651 //\r
2652\r
2653 //\r
2654 // Date question is not in IFR Form. This IFR form is not valid. \r
2655 //\r
22031c4f 2656 if (VarStoreId == 0) {\r
d9bbabfd
ED
2657 Status = EFI_INVALID_PARAMETER;\r
2658 goto Done;\r
2659 }\r
2660 //\r
2661 // Check whether this question is for the requested varstore.\r
2662 //\r
2663 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;\r
22031c4f 2664 if (IfrDate->Question.VarStoreId != VarStoreId) {\r
d9bbabfd
ED
2665 break;\r
2666 }\r
2667\r
f447734e
DB
2668 //\r
2669 // The BlockData may allocate by other opcode,need to clean.\r
2670 //\r
2671 if (BlockData != NULL){\r
2672 BlockData = NULL;\r
2673 }\r
2674\r
d9bbabfd 2675 VarWidth = (UINT16) sizeof (EFI_HII_DATE);\r
37cd16ac 2676 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2677 if (EFI_ERROR (Status)) {\r
f447734e
DB
2678 if (Status == EFI_NOT_FOUND){\r
2679 //\r
2680 //The opcode is not required,exit and parse other opcode.\r
2681 //\r
2682 break;\r
2683 }\r
d9bbabfd
ED
2684 goto Done;\r
2685 }\r
d9bbabfd
ED
2686 break;\r
2687\r
2688 case EFI_IFR_TIME_OP:\r
2689 //\r
2690 // offset by question header\r
2691 // width MaxSize * sizeof (CHAR16)\r
2692 // no default value, only block array\r
2693 //\r
2694\r
2695 //\r
2696 // Time question is not in IFR Form. This IFR form is not valid. \r
2697 //\r
22031c4f 2698 if (VarStoreId == 0) {\r
d9bbabfd
ED
2699 Status = EFI_INVALID_PARAMETER;\r
2700 goto Done;\r
2701 }\r
2702 //\r
2703 // Check whether this question is for the requested varstore.\r
2704 //\r
2705 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;\r
22031c4f 2706 if (IfrTime->Question.VarStoreId != VarStoreId) {\r
d9bbabfd
ED
2707 break;\r
2708 }\r
2709\r
f447734e
DB
2710 //\r
2711 // The BlockData may allocate by other opcode,need to clean.\r
2712 //\r
2713 if (BlockData != NULL){\r
2714 BlockData = NULL;\r
2715 }\r
2716\r
d9bbabfd 2717 VarWidth = (UINT16) sizeof (EFI_HII_TIME);\r
37cd16ac 2718 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2719 if (EFI_ERROR (Status)) {\r
f447734e
DB
2720 if (Status == EFI_NOT_FOUND){\r
2721 //\r
2722 //The opcode is not required,exit and parse other opcode.\r
2723 //\r
2724 break;\r
2725 }\r
d9bbabfd
ED
2726 goto Done;\r
2727 }\r
d9bbabfd
ED
2728 break;\r
2729\r
84f9a9ec
LG
2730 case EFI_IFR_STRING_OP:\r
2731 //\r
2732 // offset by question header\r
2733 // width MaxSize * sizeof (CHAR16)\r
2734 // no default value, only block array\r
2735 //\r
2736\r
8567300a
LG
2737 //\r
2738 // String question is not in IFR Form. This IFR form is not valid. \r
2739 //\r
22031c4f 2740 if (VarStoreId == 0) {\r
8567300a
LG
2741 Status = EFI_INVALID_PARAMETER;\r
2742 goto Done;\r
2743 }\r
84f9a9ec
LG
2744 //\r
2745 // Check whether this question is for the requested varstore.\r
2746 //\r
2747 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
22031c4f 2748 if (IfrString->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2749 break;\r
2750 }\r
84f9a9ec 2751\r
f447734e
DB
2752 //\r
2753 // The BlockData may allocate by other opcode,need to clean.\r
2754 //\r
2755 if (BlockData != NULL){\r
2756 BlockData = NULL;\r
2757 }\r
2758\r
82e8c138 2759 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
37cd16ac 2760 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2761 if (EFI_ERROR (Status)) {\r
f447734e
DB
2762 if (Status == EFI_NOT_FOUND){\r
2763 //\r
2764 //The opcode is not required,exit and parse other opcode.\r
2765 //\r
2766 break;\r
2767 }\r
84f9a9ec
LG
2768 goto Done;\r
2769 }\r
84f9a9ec
LG
2770 break;\r
2771\r
2772 case EFI_IFR_PASSWORD_OP:\r
2773 //\r
2774 // offset by question header\r
2775 // width MaxSize * sizeof (CHAR16)\r
2776 // no default value, only block array\r
2777 //\r
2778\r
8567300a
LG
2779 //\r
2780 // Password question is not in IFR Form. This IFR form is not valid. \r
2781 //\r
22031c4f 2782 if (VarStoreId == 0) {\r
8567300a
LG
2783 Status = EFI_INVALID_PARAMETER;\r
2784 goto Done;\r
2785 }\r
84f9a9ec
LG
2786 //\r
2787 // Check whether this question is for the requested varstore.\r
2788 //\r
2789 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
22031c4f 2790 if (IfrPassword->Question.VarStoreId != VarStoreId) {\r
84f9a9ec
LG
2791 break;\r
2792 }\r
84f9a9ec 2793\r
f447734e
DB
2794 //\r
2795 // The BlockData may allocate by other opcode,need to clean.\r
2796 //\r
2797 if (BlockData != NULL){\r
2798 BlockData = NULL;\r
2799 }\r
2800\r
82e8c138 2801 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
37cd16ac 2802 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
82e8c138 2803 if (EFI_ERROR (Status)) {\r
f447734e
DB
2804 if (Status == EFI_NOT_FOUND){\r
2805 //\r
2806 //The opcode is not required,exit and parse other opcode.\r
2807 //\r
2808 break;\r
2809 }\r
84f9a9ec
LG
2810 goto Done;\r
2811 }\r
82e8c138 2812\r
84f9a9ec
LG
2813 //\r
2814 // No default value for string.\r
2815 //\r
2816 BlockData = NULL;\r
2817 break;\r
2818\r
2819 case EFI_IFR_ONE_OF_OPTION_OP:\r
2820 //\r
2821 // No matched block data is ignored.\r
2822 //\r
2823 if (BlockData == NULL || BlockData->Scope == 0) {\r
2824 break;\r
2825 }\r
82e8c138 2826\r
84f9a9ec
LG
2827 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
2828 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
9495c01e
DB
2829\r
2830 if (!FirstOrderedList){\r
2831 break;\r
2832 }\r
84f9a9ec
LG
2833 //\r
2834 // Get ordered list option data type.\r
2835 //\r
2836 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
2837 VarWidth = 1;\r
2838 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
2839 VarWidth = 2;\r
2840 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
2841 VarWidth = 4;\r
2842 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
2843 VarWidth = 8;\r
2844 } else {\r
2845 //\r
2846 // Invalid ordered list option data type.\r
2847 //\r
2848 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
2849 if (BlockData->Name != NULL) {\r
2850 FreePool (BlockData->Name);\r
2851 }\r
ff28420b 2852 FreePool (BlockData);\r
84f9a9ec
LG
2853 goto Done;\r
2854 }\r
ff28420b 2855\r
84f9a9ec
LG
2856 //\r
2857 // Calculate Ordered list QuestionId width.\r
2858 //\r
2859 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
ff28420b
LG
2860 //\r
2861 // Check whether this question is in requested block array.\r
2862 //\r
70066a82 2863 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
ff28420b
LG
2864 //\r
2865 // This question is not in the requested string. Skip it.\r
2866 //\r
82e8c138
ED
2867 if (BlockData->Name != NULL) {\r
2868 FreePool (BlockData->Name);\r
2869 }\r
ff28420b
LG
2870 FreePool (BlockData);\r
2871 BlockData = NULL;\r
2872 break;\r
2873 }\r
2874 //\r
2875 // Check this var question is in the var storage \r
2876 //\r
82e8c138 2877 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
ff28420b 2878 Status = EFI_INVALID_PARAMETER;\r
82e8c138
ED
2879 if (BlockData->Name != NULL) {\r
2880 FreePool (BlockData->Name);\r
2881 }\r
ff28420b
LG
2882 FreePool (BlockData);\r
2883 goto Done;\r
2884 }\r
2885 //\r
2886 // Add Block Data into VarStorageData BlockEntry\r
2887 //\r
2888 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
9495c01e
DB
2889\r
2890 FirstOrderedList = FALSE;\r
2891\r
84f9a9ec
LG
2892 break;\r
2893 }\r
2894\r
ef40f0f6
ED
2895 //\r
2896 // 1. Set default value for OneOf option when flag field has default attribute.\r
22f63ff6 2897 // And set the default value with the smallest default id for other default id in the DefaultId list.\r
ef40f0f6 2898 //\r
cf4c5a42 2899 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
ef40f0f6 2900 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {\r
cf4c5a42
LG
2901 //\r
2902 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2903 // The first oneof option value will be used as default value when no default value is specified. \r
2904 //\r
2905 FirstOneOfOption = FALSE;\r
22f63ff6
DB
2906\r
2907 SmallestIdFromFlag = FALSE;\r
ef40f0f6 2908 \r
84f9a9ec
LG
2909 // Prepare new DefaultValue\r
2910 //\r
82e8c138 2911 DefaultData.Type = DefaultValueFromFlag;\r
a7f87053 2912 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2913 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
2914 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2915 InsertDefaultValue (BlockData, &DefaultData);\r
22f63ff6
DB
2916 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2917 //\r
2918 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2919 //\r
2920 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2921 SmallestIdFromFlag = TRUE;\r
2922 }\r
2923 }\r
ef40f0f6
ED
2924 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
2925 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2926 InsertDefaultValue (BlockData, &DefaultData);\r
22f63ff6
DB
2927 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2928 //\r
2929 // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
2930 //\r
2931 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2932 SmallestIdFromFlag = TRUE;\r
2933 }\r
2934 }\r
2935\r
2936 if (SmallestIdFromFlag) {\r
2937 //\r
2938 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.\r
2939 //\r
2940 DefaultData.Type = DefaultValueFromOtherDefault;\r
2941 //\r
2942 // Set default value for other default id in the DefaultId list.\r
2943 //\r
2944 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2945 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
2946 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2947 InsertDefaultValue (BlockData, &DefaultData);\r
2948 }\r
84f9a9ec 2949 }\r
ef40f0f6 2950 }\r
82e8c138 2951\r
ef40f0f6
ED
2952 //\r
2953 // 2. Set as the default value when this is the first option.\r
2954 // The first oneof option value will be used as default value when no default value is specified. \r
2955 //\r
2956 if (FirstOneOfOption) {\r
2957 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
2958 FirstOneOfOption = FALSE;\r
2959 \r
84f9a9ec
LG
2960 //\r
2961 // Prepare new DefaultValue\r
ef40f0f6 2962 // \r
82e8c138 2963 DefaultData.Type = DefaultValueFromDefault;\r
a7f87053 2964 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
ef40f0f6
ED
2965 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
2966 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry); \r
2967 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
2968 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 2969 }\r
84f9a9ec
LG
2970 }\r
2971 break;\r
2972\r
2973 case EFI_IFR_DEFAULT_OP:\r
2974 //\r
2975 // Update Current BlockData to the default value.\r
2976 //\r
2977 if (BlockData == NULL || BlockData->Scope == 0) {\r
2978 //\r
82e8c138 2979 // No matched block data is ignored.\r
84f9a9ec
LG
2980 //\r
2981 break;\r
2982 }\r
2983\r
84f9a9ec 2984 //\r
81b618fe 2985 // Get the DefaultId\r
84f9a9ec
LG
2986 //\r
2987 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
2988 VarDefaultId = IfrDefault->DefaultId;\r
84f9a9ec
LG
2989 //\r
2990 // Prepare new DefaultValue\r
2991 //\r
eb5e7d3e 2992 DefaultData.Type = DefaultValueFromOpcode;\r
ef40f0f6 2993 DefaultData.DefaultId = VarDefaultId;\r
37cd16ac
DB
2994 if (QuestionReferBitField) {\r
2995 CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));\r
2996 } else {\r
2997 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
2998 }\r
82e8c138 2999\r
ef40f0f6
ED
3000 // If the value field is expression, set the cleaned flag.\r
3001 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
3002 DefaultData.Cleaned = TRUE;\r
84f9a9ec 3003 }\r
84f9a9ec
LG
3004 //\r
3005 // Add DefaultValue into current BlockData\r
3006 //\r
ef40f0f6 3007 InsertDefaultValue (BlockData, &DefaultData);\r
82e8c138 3008\r
22f63ff6
DB
3009 //\r
3010 // Set default value for other default id in the DefaultId list.\r
3011 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.\r
3012 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.\r
3013 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.\r
3014 //\r
3015 if ((SmallestDefaultId > VarDefaultId) || (SmallestDefaultId == VarDefaultId && !FromOtherDefaultOpcode)) {\r
3016 FromOtherDefaultOpcode = TRUE;\r
3017 SmallestDefaultId = VarDefaultId;\r
3018 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
3019 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
3020 if (DefaultDataPtr->DefaultId != DefaultData.DefaultId){\r
3021 DefaultData.Type = DefaultValueFromOtherDefault;\r
3022 DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
3023 InsertDefaultValue (BlockData, &DefaultData);\r
3024 }\r
3025 }\r
3026 }\r
3027\r
ef40f0f6 3028 //\r
4a429716
RN
3029 // After insert the default value, reset the cleaned value for next\r
3030 // time used. If not set here, need to set the value before every time.\r
ef40f0f6
ED
3031 // use it.\r
3032 //\r
3033 DefaultData.Cleaned = FALSE;\r
84f9a9ec 3034 break;\r
82e8c138 3035\r
84f9a9ec
LG
3036 case EFI_IFR_END_OP:\r
3037 //\r
8567300a 3038 // End Opcode is for Var question.\r
84f9a9ec 3039 //\r
37cd16ac 3040 QuestionReferBitField = FALSE;\r
7248790e
ED
3041 if (BlockData != NULL) {\r
3042 if (BlockData->Scope > 0) {\r
3043 BlockData->Scope--;\r
3044 }\r
3045 if (BlockData->Scope == 0) {\r
3046 BlockData = NULL;\r
22f63ff6
DB
3047 //\r
3048 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.\r
3049 //\r
3050 SmallestDefaultId = 0xFFFF;\r
3051 FromOtherDefaultOpcode = FALSE;\r
7248790e 3052 }\r
84f9a9ec 3053 }\r
7248790e 3054\r
84f9a9ec 3055 break;\r
82e8c138 3056\r
37cd16ac
DB
3057 case EFI_IFR_GUID_OP:\r
3058 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
3059 QuestionReferBitField = TRUE;\r
3060 }\r
3061 break;\r
3062\r
84f9a9ec 3063 default:\r
7248790e
ED
3064 if (BlockData != NULL) {\r
3065 if (BlockData->Scope > 0) {\r
3066 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
3067 }\r
3068\r
3069 if (BlockData->Scope == 0) {\r
3070 BlockData = NULL;\r
3071 }\r
84f9a9ec
LG
3072 }\r
3073 break;\r
3074 }\r
3075\r
22031c4f
ED
3076 IfrOffset += IfrOpHdr->Length;\r
3077 PackageOffset += IfrOpHdr->Length;\r
84f9a9ec
LG
3078 }\r
3079\r
f447734e
DB
3080 //\r
3081 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,\r
3082 //so set the Status to EFI_SUCCESS.\r
3083 //\r
3084 if (Status == EFI_NOT_FOUND){\r
3085 Status = EFI_SUCCESS;\r
3086 }\r
3087\r
84f9a9ec 3088Done:\r
ef40f0f6
ED
3089 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
3090 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
3091 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
3092 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
3093 LinkDefault = LinkDefault->ForwardLink;\r
3094 if (DefaultDataPtr->Cleaned == TRUE) {\r
3095 RemoveEntryList (&DefaultDataPtr->Entry);\r
3096 FreePool (DefaultDataPtr);\r
3097 }\r
3098 }\r
3099 }\r
3100\r
82e8c138 3101 return Status;\r
84f9a9ec
LG
3102}\r
3103\r
3104/**\r
82e8c138 3105 parse the configrequest string, get the elements.\r
84f9a9ec 3106\r
82e8c138
ED
3107 @param ConfigRequest The input configrequest string.\r
3108 @param Progress Return the progress data.\r
3109\r
3110 @retval Block data pointer.\r
3111**/\r
3112IFR_BLOCK_DATA *\r
3113GetBlockElement (\r
3114 IN EFI_STRING ConfigRequest,\r
3115 OUT EFI_STRING *Progress\r
3116 )\r
3117{\r
3118 EFI_STRING StringPtr;\r
3119 IFR_BLOCK_DATA *BlockData;\r
3120 IFR_BLOCK_DATA *RequestBlockArray;\r
3121 EFI_STATUS Status;\r
3122 UINT8 *TmpBuffer;\r
3123 UINT16 Offset;\r
3124 UINT16 Width;\r
3125 LIST_ENTRY *Link;\r
3126 IFR_BLOCK_DATA *NextBlockData;\r
3127 UINTN Length;\r
3128\r
4e1005ec
ED
3129 TmpBuffer = NULL;\r
3130\r
82e8c138
ED
3131 //\r
3132 // Init RequestBlockArray\r
3133 //\r
3134 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
3135 if (RequestBlockArray == NULL) {\r
3136 goto Done;\r
3137 }\r
3138 InitializeListHead (&RequestBlockArray->Entry);\r
3139\r
3140 //\r
3141 // Get the request Block array from the request string\r
3142 // Offset and Width\r
3143 //\r
3144\r
3145 //\r
3146 // Parse each <RequestElement> if exists\r
3147 // Only <BlockName> format is supported by this help function.\r
3148 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
3149 //\r
3150 StringPtr = ConfigRequest;\r
3151 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
3152 //\r
3153 // Skip the OFFSET string\r
3154 //\r
3155 *Progress = StringPtr;\r
3156 StringPtr += StrLen (L"&OFFSET=");\r
3157 //\r
3158 // Get Offset\r
3159 //\r
3160 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3161 if (EFI_ERROR (Status)) {\r
3162 goto Done;\r
3163 }\r
3164 Offset = 0;\r
3165 CopyMem (\r
3166 &Offset,\r
3167 TmpBuffer,\r
3168 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
3169 );\r
3170 FreePool (TmpBuffer);\r
3171\r
3172 StringPtr += Length;\r
3173 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
3174 goto Done;\r
3175 }\r
3176 StringPtr += StrLen (L"&WIDTH=");\r
3177\r
3178 //\r
3179 // Get Width\r
3180 //\r
3181 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3182 if (EFI_ERROR (Status)) {\r
3183 goto Done;\r
3184 }\r
3185 Width = 0;\r
3186 CopyMem (\r
3187 &Width,\r
3188 TmpBuffer,\r
3189 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
3190 );\r
3191 FreePool (TmpBuffer);\r
3192\r
3193 StringPtr += Length;\r
3194 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3195 goto Done;\r
3196 }\r
3197 \r
3198 //\r
3199 // Set Block Data\r
3200 //\r
3201 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
3202 if (BlockData == NULL) {\r
3203 goto Done;\r
3204 }\r
3205 BlockData->Offset = Offset;\r
3206 BlockData->Width = Width;\r
3207 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
3208\r
3209 //\r
3210 // Skip &VALUE string if &VALUE does exists.\r
3211 //\r
3212 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
3213 StringPtr += StrLen (L"&VALUE=");\r
3214\r
3215 //\r
3216 // Get Value\r
3217 //\r
3218 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3219 if (EFI_ERROR (Status)) {\r
3220 goto Done;\r
3221 }\r
a0b0cd73 3222 FreePool (TmpBuffer);\r
82e8c138
ED
3223 StringPtr += Length;\r
3224 if (*StringPtr != 0 && *StringPtr != L'&') {\r
3225 goto Done;\r
3226 }\r
3227 }\r
3228 //\r
3229 // If '\0', parsing is finished. \r
3230 //\r
3231 if (*StringPtr == 0) {\r
3232 break;\r
3233 }\r
3234 }\r
3235\r
3236 //\r
3237 // Merge the requested block data.\r
3238 //\r
3239 Link = RequestBlockArray->Entry.ForwardLink;\r
3240 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
3241 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3242 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
3243 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
3244 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
3245 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
3246 }\r
3247 RemoveEntryList (Link->ForwardLink);\r
3248 FreePool (NextBlockData);\r
3249 continue;\r
3250 }\r
3251 Link = Link->ForwardLink;\r
3252 }\r
3253\r
3254 return RequestBlockArray;\r
3255\r
3256Done:\r
3257 if (RequestBlockArray != NULL) {\r
3258 //\r
3259 // Free Link Array RequestBlockArray\r
3260 //\r
3261 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3262 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3263 RemoveEntryList (&BlockData->Entry);\r
3264 FreePool (BlockData);\r
3265 }\r
3266\r
3267 FreePool (RequestBlockArray);\r
3268 }\r
3269\r
3270 return NULL;\r
3271}\r
3272\r
3273/**\r
3274 parse the configrequest string, get the elements.\r
3275\r
3276 @param ConfigRequest The input config request string.\r
3277 @param Progress Return the progress data.\r
3278\r
3279 @retval return data block array.\r
3280**/\r
3281IFR_BLOCK_DATA *\r
3282GetNameElement (\r
3283 IN EFI_STRING ConfigRequest,\r
3284 OUT EFI_STRING *Progress\r
3285 )\r
3286{\r
3287 EFI_STRING StringPtr;\r
3288 EFI_STRING NextTag;\r
3289 IFR_BLOCK_DATA *BlockData;\r
3290 IFR_BLOCK_DATA *RequestBlockArray;\r
3291 BOOLEAN HasValue;\r
3292\r
3293 StringPtr = ConfigRequest;\r
3294\r
3295 //\r
3296 // Init RequestBlockArray\r
3297 //\r
3298 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
3299 if (RequestBlockArray == NULL) {\r
3300 goto Done;\r
3301 }\r
3302 InitializeListHead (&RequestBlockArray->Entry);\r
3303\r
3304 //\r
3305 // Get the request Block array from the request string\r
3306 //\r
3307\r
3308 //\r
3309 // Parse each <RequestElement> if exists\r
3310 // Only <BlockName> format is supported by this help function.\r
3311 // <BlockName> ::= &'Name***=***\r
3312 //\r
3313 while (StringPtr != NULL && *StringPtr == L'&') {\r
3314\r
3315 *Progress = StringPtr;\r
3316 //\r
3317 // Skip the L"&" string\r
3318 //\r
3319 StringPtr += 1;\r
3320\r
3321 HasValue = FALSE;\r
3322 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
3323 *NextTag = L'\0';\r
3324 HasValue = TRUE;\r
3325 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
3326 *NextTag = L'\0';\r
3327 }\r
3328\r
3329 //\r
3330 // Set Block Data\r
3331 //\r
3332 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
3333 if (BlockData == NULL) {\r
3334 goto Done;\r
3335 }\r
3336\r
3337 //\r
3338 // Get Name\r
3339 //\r
3340 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
3341 InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
3342\r
3343 if (HasValue) {\r
3344 //\r
3345 // If has value, skip the value.\r
3346 // \r
3347 StringPtr = NextTag + 1;\r
3348 *NextTag = L'=';\r
3349 StringPtr = StrStr (StringPtr, L"&");\r
3350 } else if (NextTag != NULL) {\r
3351 //\r
3352 // restore the '&' text.\r
3353 //\r
3354 StringPtr = NextTag;\r
3355 *NextTag = L'&';\r
3356 }\r
3357 }\r
3358\r
3359 return RequestBlockArray;\r
3360\r
3361Done:\r
3362 if (RequestBlockArray != NULL) {\r
3363 //\r
3364 // Free Link Array RequestBlockArray\r
3365 //\r
3366 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
3367 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
3368 RemoveEntryList (&BlockData->Entry);\r
3369 if (BlockData->Name != NULL) {\r
3370 FreePool (BlockData->Name);\r
3371 }\r
3372 FreePool (BlockData);\r
3373 }\r
3374\r
3375 FreePool (RequestBlockArray);\r
3376 }\r
3377\r
3378 return NULL;\r
3379}\r
3380\r
3381/**\r
3382 Generate ConfigRequest string base on the varstore info.\r
3383\r
3384 @param ConfigHdr The config header for this varstore.\r
3385 @param VarStorageData The varstore info.\r
3386 @param Status Return Status.\r
3387 @param ConfigRequest The ConfigRequest info may be return.\r
3388\r
3389 @retval TRUE Need to continue\r
3390 @retval Others NO need to continue or error occur.\r
3391**/\r
3392BOOLEAN\r
3393GenerateConfigRequest (\r
3394 IN CHAR16 *ConfigHdr,\r
3395 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3396 OUT EFI_STATUS *Status,\r
3397 IN OUT EFI_STRING *ConfigRequest\r
3398 )\r
3399{\r
3400 BOOLEAN DataExist;\r
3401 UINTN Length;\r
3402 LIST_ENTRY *Link;\r
3403 CHAR16 *FullConfigRequest;\r
3404 CHAR16 *StringPtr;\r
3405 IFR_BLOCK_DATA *BlockData;\r
3406\r
3407 //\r
3408 // Append VarStorageData BlockEntry into *Request string\r
3409 // Now support only one varstore in a form package.\r
3410 //\r
3411 \r
3412 //\r
3413 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
3414 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
3415 //\r
3416 \r
3417 //\r
3418 // Compute the length of the entire request starting with <ConfigHdr> and a \r
3419 // Null-terminator\r
3420 //\r
3421 DataExist = FALSE;\r
3422 Length = StrLen (ConfigHdr) + 1;\r
3423\r
3424 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
3425 DataExist = TRUE;\r
3426 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3427 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3428 //\r
3429 // Add <BlockName> length for each Name\r
3430 //\r
3431 // <BlockName> ::= &Name1&Name2&... \r
3432 // |1| StrLen(Name1)\r
3433 //\r
3434 Length = Length + (1 + StrLen (BlockData->Name));\r
3435 } else {\r
3436 //\r
3437 // Add <BlockName> length for each Offset/Width pair\r
3438 //\r
3439 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
3440 // | 8 | 4 | 7 | 4 |\r
3441 //\r
3442 Length = Length + (8 + 4 + 7 + 4);\r
3443 }\r
3444 }\r
3445 //\r
3446 // No any request block data is found. The request string can't be constructed.\r
3447 //\r
3448 if (!DataExist) {\r
3449 *Status = EFI_SUCCESS;\r
3450 return FALSE;\r
3451 }\r
3452\r
3453 //\r
3454 // Allocate buffer for the entire <ConfigRequest>\r
3455 //\r
3456 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
3457 if (FullConfigRequest == NULL) {\r
3458 *Status = EFI_OUT_OF_RESOURCES;\r
3459 return FALSE;\r
3460 }\r
3461 StringPtr = FullConfigRequest;\r
3462\r
3463 //\r
3464 // Start with <ConfigHdr>\r
3465 //\r
5ad66ec6 3466 StrCpyS (StringPtr, Length, ConfigHdr);\r
82e8c138
ED
3467 StringPtr += StrLen (StringPtr);\r
3468\r
3469 //\r
3470 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
3471 //\r
3472 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
3473 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3474 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3475 //\r
3476 // Append &Name1\0\r
3477 //\r
3478 UnicodeSPrint (\r
3479 StringPtr,\r
3480 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
3481 L"&%s",\r
3482 BlockData->Name\r
3483 );\r
3484 } else {\r
3485 //\r
3486 // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
3487 //\r
3488 UnicodeSPrint (\r
3489 StringPtr, \r
3490 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
3491 L"&OFFSET=%04X&WIDTH=%04X", \r
3492 BlockData->Offset, \r
3493 BlockData->Width\r
3494 );\r
3495 }\r
3496 StringPtr += StrLen (StringPtr);\r
3497 }\r
3498 //\r
3499 // Set to the got full request string.\r
3500 //\r
3501 HiiToLower (FullConfigRequest);\r
3502\r
3503 if (*ConfigRequest != NULL) {\r
3504 FreePool (*ConfigRequest);\r
3505 }\r
3506 *ConfigRequest = FullConfigRequest;\r
3507\r
3508 return TRUE;\r
3509}\r
3510\r
3511/**\r
3512 Generate ConfigRequest Header base on the varstore info.\r
3513\r
3514 @param VarStorageData The varstore info.\r
3515 @param DevicePath Device path for this varstore.\r
3516 @param ConfigHdr The config header for this varstore.\r
3517\r
3518 @retval EFI_SUCCESS Generate the header success.\r
3519 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
3520**/\r
3521EFI_STATUS\r
3522GenerateHdr (\r
3523 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3524 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
3525 OUT EFI_STRING *ConfigHdr\r
3526 )\r
3527{\r
3528 EFI_STRING GuidStr;\r
3529 EFI_STRING NameStr;\r
3530 EFI_STRING PathStr;\r
3531 UINTN Length;\r
3532 EFI_STATUS Status;\r
3533\r
3534 Status = EFI_SUCCESS;\r
3535 NameStr = NULL;\r
3536 GuidStr = NULL;\r
3537 PathStr = NULL;\r
3538\r
3539 //\r
3540 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
3541 //\r
3542 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
3543 if (VarStorageData->Name != NULL) {\r
3544 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
3545 } else {\r
3546 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
3547 }\r
3548 GenerateSubStr (\r
3549 L"PATH=",\r
3550 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
3551 (VOID *) DevicePath,\r
3552 1,\r
3553 &PathStr\r
3554 );\r
3555 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
3556 if (VarStorageData->Name == NULL) {\r
3557 Length += 1;\r
3558 }\r
3559\r
3560 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
3561 if (*ConfigHdr == NULL) {\r
3562 Status = EFI_OUT_OF_RESOURCES;\r
3563 goto Done;\r
3564 }\r
5ad66ec6
DB
3565 StrCpyS (*ConfigHdr, Length, GuidStr);\r
3566 StrCatS (*ConfigHdr, Length, NameStr);\r
82e8c138 3567 if (VarStorageData->Name == NULL) {\r
5ad66ec6 3568 StrCatS (*ConfigHdr, Length, L"&");\r
82e8c138 3569 }\r
5ad66ec6 3570 StrCatS (*ConfigHdr, Length, PathStr);\r
82e8c138
ED
3571\r
3572 //\r
3573 // Remove the last character L'&'\r
3574 //\r
3575 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
3576\r
3577Done:\r
3578 if (GuidStr != NULL) {\r
3579 FreePool (GuidStr);\r
3580 }\r
3581\r
3582 if (NameStr != NULL) {\r
3583 FreePool (NameStr);\r
3584 }\r
3585\r
3586 if (PathStr != NULL) {\r
3587 FreePool (PathStr);\r
3588 }\r
3589\r
3590 return Status;\r
3591}\r
3592\r
3593/**\r
3594 Get Data buffer size based on data type.\r
3595\r
3596 @param ValueType The input data type.\r
3597\r
3598 @retval The data buffer size for the input type.\r
3599**/\r
3600UINT16\r
3601GetStorageWidth (\r
3602 IN UINT8 ValueType\r
3603 )\r
3604{\r
3605 UINT16 StorageWidth;\r
3606\r
3607 switch (ValueType) {\r
3608 case EFI_IFR_NUMERIC_SIZE_1:\r
3609 case EFI_IFR_TYPE_BOOLEAN:\r
3610 StorageWidth = (UINT16) sizeof (UINT8);\r
3611 break;\r
3612\r
3613 case EFI_IFR_NUMERIC_SIZE_2:\r
3614 StorageWidth = (UINT16) sizeof (UINT16);\r
3615 break;\r
3616\r
3617 case EFI_IFR_NUMERIC_SIZE_4:\r
3618 StorageWidth = (UINT16) sizeof (UINT32);\r
3619 break;\r
3620\r
3621 case EFI_IFR_NUMERIC_SIZE_8:\r
3622 StorageWidth = (UINT16) sizeof (UINT64);\r
3623 break;\r
3624\r
3625 case EFI_IFR_TYPE_TIME:\r
3626 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
3627 break;\r
3628\r
3629 case EFI_IFR_TYPE_DATE:\r
3630 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
3631 break;\r
3632\r
3633 default:\r
3634 StorageWidth = 0;\r
3635 break;\r
3636 }\r
3637\r
3638 return StorageWidth;\r
3639}\r
3640\r
37cd16ac
DB
3641/**\r
3642 Update the default value in the block data which is used as bit var store.\r
3643\r
3644 For example:\r
3645 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.\r
3646 And corresponding block data info: offset==0; width==1;currently the default value\r
3647 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the\r
3648 default value of this block data shuold be:2.\r
3649\r
3650 typedef struct {\r
3651 UINT8 Bit1 : 1; //\r
3652 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.\r
3653 // (default value record for the bit field)\r
3654 ......\r
3655 }ExampleData;\r
3656\r
3657 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.\r
3658 (default value record for the Block)\r
3659\r
3660 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.\r
3661\r
3662 @param BlockLink The Link of the block data.\r
3663\r
3664**/\r
3665VOID\r
3666UpdateDefaultValue (\r
3667 IN LIST_ENTRY *BlockLink\r
3668)\r
3669{\r
3670 LIST_ENTRY *Link;\r
3671 LIST_ENTRY *ListEntry;\r
3672 LIST_ENTRY *LinkDefault;\r
3673 IFR_BLOCK_DATA *BlockData;\r
3674 IFR_DEFAULT_DATA *DefaultValueData;\r
3675 UINTN StartBit;\r
3676 UINTN EndBit;\r
3677 UINT32 BitFieldDefaultValue;\r
3678\r
3679 for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
3680 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3681 if (!BlockData ->IsBitVar) {\r
3682 continue;\r
3683 }\r
3684 ListEntry = &BlockData->DefaultValueEntry;\r
3685 //\r
3686 // Update the default value in the block data with all existing default id.\r
3687 //\r
3688 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
3689 //\r
3690 // Get the default data, and the value of the default data is for some field in the block.\r
3691 // Note: Default value for bit field question is stored as UINT32.\r
3692 //\r
3693 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
3694 BitFieldDefaultValue = DefaultValueData->Value.u32;\r
3695\r
3696 StartBit = BlockData->BitOffset % 8;\r
3697 EndBit = StartBit + BlockData->BitWidth - 1;\r
3698\r
3699 //\r
3700 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.\r
3701 //\r
3702 DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);\r
3703 }\r
3704 }\r
3705}\r
3706\r
3707/**\r
3708Merge the default value in two block datas which have overlap region.\r
3709\r
3710For bit fields, their related block data may have overlap region, such as:\r
3711\r
3712typedef struct {\r
3713 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1\r
3714 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5\r
3715 // (default value record for the bit field)\r
3716 ......\r
3717}ExampleData;\r
3718\r
3719After function UpdateDefaultValue:\r
3720Block1: offset = 0; width = 1;(byte level) default = 1\r
3721Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))\r
3722(default value record for block)\r
3723\r
3724After function MergeBlockDefaultValue:\r
3725Block1: offset = 0; width = 1;(byte level) default = 65\r
3726Block2: offset = 0; width = 2;(byte level) default = 321\r
3727(Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)\r
3728\r
3729Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains\r
3730value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).\r
3731\r
3732This fuction merge the default value of these two blocks, and make the default value of block1\r
3733also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also\r
3734contain the default value of Bit1.\r
3735\r
3736We can get the total value of the whole block that just cover these two blocks(in this case is:\r
3737block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is\r
3738the first byte value of block.\r
3739\r
3740@param FirstBlock Point to the block date whose default value need to be merged.\r
3741@param SecondBlock Point to the block date whose default value need to be merged.\r
3742\r
3743**/\r
3744VOID\r
3745MergeBlockDefaultValue (\r
3746 IN OUT IFR_BLOCK_DATA *FirstBlock,\r
3747 IN OUT IFR_BLOCK_DATA *SecondBlock\r
3748)\r
3749{\r
3750 LIST_ENTRY *FirstListEntry;\r
3751 LIST_ENTRY *SecondListEntry;\r
3752 LIST_ENTRY *FirstDefaultLink;\r
3753 LIST_ENTRY *SecondDefaultLink;\r
3754 IFR_DEFAULT_DATA *FirstDefaultValueData;\r
3755 IFR_DEFAULT_DATA *SecondDefaultValueData;\r
3756 UINT32 *FirstDefaultValue;\r
3757 UINT32 *SecondDefaultValue;\r
3758 UINT64 TotalValue;\r
3759 UINT64 ShiftedValue;\r
3760 UINT16 OffsetShift;\r
3761\r
3762 FirstListEntry = &FirstBlock->DefaultValueEntry;\r
3763 for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {\r
3764 FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);\r
3765 SecondListEntry = &SecondBlock->DefaultValueEntry;\r
3766 for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {\r
3767 SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);\r
3768 if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {\r
3769 continue;\r
3770 }\r
3771 //\r
3772 // Find default value with same default id in the two blocks.\r
3773 // Note: Default value for bit field question is stored as UINT32 type.\r
3774 //\r
3775 FirstDefaultValue = &FirstDefaultValueData->Value.u32;\r
3776 SecondDefaultValue = &SecondDefaultValueData->Value.u32;\r
3777 //\r
3778 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.\r
3779 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based\r
3780 // on the offset and width of FirstBlock and SecondBlock.\r
3781 //\r
3782 if (FirstBlock->Offset > SecondBlock->Offset) {\r
3783 OffsetShift = FirstBlock->Offset - SecondBlock->Offset;\r
3784 ShiftedValue = LShiftU64 ((UINT64) (*FirstDefaultValue), OffsetShift * 8);\r
3785 TotalValue = ShiftedValue | (UINT64) (*SecondDefaultValue);\r
3786 *SecondDefaultValue = (UINT32) BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);\r
3787 *FirstDefaultValue = (UINT32) BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);\r
3788 } else {\r
3789 OffsetShift = SecondBlock->Offset -FirstBlock->Offset;\r
3790 ShiftedValue = LShiftU64 ((UINT64) (*SecondDefaultValue), OffsetShift * 8);\r
3791 TotalValue = ShiftedValue | (UINT64) (*FirstDefaultValue);\r
3792 *FirstDefaultValue = (UINT32) BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);\r
3793 *SecondDefaultValue = (UINT32) BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);\r
3794 }\r
3795 }\r
3796 }\r
3797}\r
3798\r
3799/**\r
3800\r
3801Update the default value in the block data which used as Bit VarStore\r
3802\r
3803@param BlockLink The Link of the block data.\r
3804\r
3805**/\r
3806VOID\r
3807UpdateBlockDataArray (\r
3808 IN LIST_ENTRY *BlockLink\r
3809)\r
3810{\r
3811 LIST_ENTRY *Link;\r
3812 LIST_ENTRY *TempLink;\r
3813 IFR_BLOCK_DATA *BlockData;\r
3814 IFR_BLOCK_DATA *NextBlockData;\r
3815\r
3816 //\r
3817 // 1. Update default value in BitVar block data.\r
3818 // Sine some block datas are used as BitVarStore, then the default value recored in the block\r
3819 // is for related bit field in the block. so we need to set the default value to the related bit\r
3820 // fields in the block data if the block data is used as bit varstore, then the default value of\r
3821 // the block will be updated.\r
3822 //\r
3823 UpdateDefaultValue (BlockLink);\r
3824\r
3825 //\r
3826 // 2.Update default value for overlap BitVar blcok datas.\r
3827 // For block datas have overlap region, we need to merge the default value in different blocks.\r
3828 //\r
3829 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
3830 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
3831 if (!BlockData ->IsBitVar) {\r
3832 continue;\r
3833 }\r
3834 for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {\r
3835 NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);\r
3836 if (!NextBlockData->IsBitVar || NextBlockData->Offset >= BlockData->Offset + BlockData->Width || BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width) {\r
3837 continue;\r
3838 }\r
3839 //\r
3840 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.\r
3841 //\r
3842 MergeBlockDefaultValue (BlockData, NextBlockData);\r
3843 }\r
3844 }\r
3845}\r
3846\r
82e8c138
ED
3847/**\r
3848 Generate ConfigAltResp string base on the varstore info.\r
3849\r
e68c776b 3850 @param HiiHandle Hii Handle for this hii package.\r
82e8c138
ED
3851 @param ConfigHdr The config header for this varstore.\r
3852 @param VarStorageData The varstore info.\r
3853 @param DefaultIdArray The Default id array.\r
3854 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
3855\r
3856 @retval TRUE Need to continue\r
3857 @retval Others NO need to continue or error occur.\r
3858**/\r
3859EFI_STATUS\r
3860GenerateAltConfigResp (\r
e68c776b 3861 IN EFI_HII_HANDLE HiiHandle,\r
82e8c138
ED
3862 IN CHAR16 *ConfigHdr,\r
3863 IN IFR_VARSTORAGE_DATA *VarStorageData,\r
3864 IN IFR_DEFAULT_DATA *DefaultIdArray,\r
3865 IN OUT EFI_STRING *DefaultAltCfgResp\r
3866 )\r
3867{\r
3868 BOOLEAN DataExist;\r
3869 UINTN Length;\r
3870 LIST_ENTRY *Link;\r
3871 LIST_ENTRY *LinkData;\r
3872 LIST_ENTRY *LinkDefault;\r
3873 LIST_ENTRY *ListEntry;\r
3874 CHAR16 *StringPtr;\r
3875 IFR_BLOCK_DATA *BlockData;\r
3876 IFR_DEFAULT_DATA *DefaultId;\r
3877 IFR_DEFAULT_DATA *DefaultValueData;\r
3878 UINTN Width;\r
3879 UINT8 *TmpBuffer;\r
e68c776b 3880 CHAR16 *DefaultString;\r
bf342907 3881 UINTN StrSize;\r
82e8c138
ED
3882\r
3883 BlockData = NULL;\r
3884 DataExist = FALSE;\r
e68c776b 3885 DefaultString = NULL;\r
82e8c138
ED
3886 //\r
3887 // Add length for <ConfigHdr> + '\0'\r
3888 //\r
3889 Length = StrLen (ConfigHdr) + 1;\r
3890\r
37cd16ac
DB
3891 UpdateBlockDataArray (&VarStorageData->BlockEntry);\r
3892\r
82e8c138
ED
3893 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
3894 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
3895 //\r
3896 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
3897 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
3898 //\r
3899 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
3900 \r
3901 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
3902 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
3903 ListEntry = &BlockData->DefaultValueEntry;\r
3904 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
3905 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
3906 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
3907 continue;\r
3908 }\r
3909 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3910 //\r
3911 // Add length for "&Name1=zzzzzzzzzzzz"\r
3912 // |1|Name|1|Value|\r
3913 //\r
3914 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
3915 } else {\r
3916 //\r
3917 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
3918 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
3919 //\r
3920 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
3921 }\r
3922 DataExist = TRUE;\r
3923 }\r
3924 }\r
3925 }\r
3926 \r
3927 //\r
3928 // No default value is found. The default string doesn't exist.\r
3929 //\r
3930 if (!DataExist) {\r
3931 return EFI_SUCCESS;\r
3932 }\r
3933\r
3934 //\r
3935 // Allocate buffer for the entire <DefaultAltCfgResp>\r
3936 //\r
3937 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
3938 if (*DefaultAltCfgResp == NULL) {\r
3939 return EFI_OUT_OF_RESOURCES;\r
3940 }\r
3941 StringPtr = *DefaultAltCfgResp;\r
3942\r
3943 //\r
3944 // Start with <ConfigHdr>\r
3945 //\r
5ad66ec6 3946 StrCpyS (StringPtr, Length, ConfigHdr);\r
82e8c138
ED
3947 StringPtr += StrLen (StringPtr);\r
3948\r
3949 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
3950 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
3951 //\r
3952 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
3953 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
3954 //\r
3955 UnicodeSPrint (\r
3956 StringPtr, \r
3957 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
3958 L"&%s&ALTCFG=%04X", \r
3959 ConfigHdr, \r
3960 DefaultId->DefaultId\r
3961 );\r
3962 StringPtr += StrLen (StringPtr);\r
3963\r
3964 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
3965 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
3966 ListEntry = &BlockData->DefaultValueEntry;\r
3967 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
3968 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
3969 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
3970 continue;\r
3971 }\r
3972 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
3973 UnicodeSPrint (\r
3974 StringPtr, \r
3975 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
3976 L"&%s=", \r
3977 BlockData->Name\r
3978 );\r
3979 StringPtr += StrLen (StringPtr);\r
3980 } else {\r
3981 //\r
3982 // Add <BlockConfig>\r
3983 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
3984 //\r
3985 UnicodeSPrint (\r
3986 StringPtr, \r
3987 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
3988 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
3989 BlockData->Offset, \r
3990 BlockData->Width\r
3991 );\r
3992 StringPtr += StrLen (StringPtr);\r
3993 }\r
3994 Width = BlockData->Width;\r
3995 //\r
3996 // Convert Value to a hex string in "%x" format\r
3997 // NOTE: This is in the opposite byte that GUID and PATH use\r
3998 //\r
e68c776b
DB
3999 if (BlockData->OpCode == EFI_IFR_STRING_OP){\r
4000 DefaultString = InternalGetString(HiiHandle, DefaultValueData->Value.string);\r
bf342907
DB
4001 TmpBuffer = AllocateZeroPool (Width);\r
4002 ASSERT (TmpBuffer != NULL);\r
4003 if (DefaultString != NULL) {\r
4004 StrSize = StrLen(DefaultString)* sizeof (CHAR16);\r
4005 if (StrSize > Width) {\r
4006 StrSize = Width;\r
4007 }\r
4008 CopyMem (TmpBuffer, (UINT8 *) DefaultString, StrSize);\r
4009 }\r
e68c776b
DB
4010 } else {\r
4011 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);\r
4012 }\r
4013 for (; Width > 0 && (TmpBuffer != NULL); Width--) {\r
9f4048f7
HW
4014 UnicodeValueToStringS (\r
4015 StringPtr,\r
4016 Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),\r
4017 PREFIX_ZERO | RADIX_HEX,\r
4018 TmpBuffer[Width - 1],\r
4019 2\r
4020 );\r
4021 StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));\r
82e8c138 4022 }\r
e68c776b
DB
4023 if (DefaultString != NULL){\r
4024 FreePool(DefaultString);\r
4025 DefaultString = NULL;\r
4026 }\r
bf342907
DB
4027 if (BlockData->OpCode == EFI_IFR_STRING_OP && TmpBuffer != NULL) {\r
4028 FreePool(TmpBuffer);\r
4029 TmpBuffer = NULL;\r
4030 }\r
82e8c138
ED
4031 }\r
4032 }\r
4033 }\r
4034\r
4035 HiiToLower (*DefaultAltCfgResp);\r
4036\r
4037 return EFI_SUCCESS;\r
4038}\r
4039\r
4040/**\r
4041 This function gets the full request string and full default value string by \r
4042 parsing IFR data in HII form packages. \r
4043 \r
4044 When Request points to NULL string, the request string and default value string \r
4045 for each varstore in form package will return. \r
4046\r
4047 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
4048 @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
4049 @param Request Pointer to a null-terminated Unicode string in\r
4050 <ConfigRequest> format. When it doesn't contain\r
4051 any RequestElement, it will be updated to return \r
4052 the full RequestElement retrieved from IFR data.\r
4053 If it points to NULL, the request string for the first\r
4054 varstore in form package will be merged into a\r
4055 <MultiConfigRequest> format string and return. \r
4056 @param AltCfgResp Pointer to a null-terminated Unicode string in\r
4057 <ConfigAltResp> format. When the pointer is to NULL,\r
4058 the full default value string retrieved from IFR data\r
4059 will return. When the pinter is to a string, the\r
4060 full default value string retrieved from IFR data\r
4061 will be merged into the input string and return.\r
4062 When Request points to NULL, the default value string \r
4063 for each varstore in form package will be merged into \r
4064 a <MultiConfigAltResp> format string and return.\r
4a429716 4065 @param PointerProgress Optional parameter, it can be NULL.\r
82e8c138
ED
4066 When it is not NULL, if Request is NULL, it returns NULL. \r
4067 On return, points to a character in the Request\r
4068 string. Points to the string's null terminator if\r
4069 request was successful. Points to the most recent\r
4070 & before the first failing name / value pair (or\r
ae79d2f9
LG
4071 the beginning of the string if the failure is in\r
4072 the first name / value pair) if the request was\r
4073 not successful.\r
84f9a9ec
LG
4074 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4075 And AltCfgResp contains all default value string.\r
4076 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
4077 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
4078 can't be found in Form package.\r
4079 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
ae79d2f9 4080 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
84f9a9ec
LG
4081\r
4082**/\r
4083EFI_STATUS\r
4084EFIAPI\r
4085GetFullStringFromHiiFormPackages (\r
8567300a 4086 IN HII_DATABASE_RECORD *DataBaseRecord,\r
84f9a9ec
LG
4087 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
4088 IN OUT EFI_STRING *Request,\r
ae79d2f9
LG
4089 IN OUT EFI_STRING *AltCfgResp,\r
4090 OUT EFI_STRING *PointerProgress OPTIONAL\r
84f9a9ec
LG
4091 )\r
4092{\r
4093 EFI_STATUS Status;\r
8567300a
LG
4094 UINT8 *HiiFormPackage;\r
4095 UINTN PackageSize;\r
84f9a9ec
LG
4096 IFR_BLOCK_DATA *RequestBlockArray;\r
4097 IFR_BLOCK_DATA *BlockData;\r
84f9a9ec
LG
4098 IFR_DEFAULT_DATA *DefaultValueData;\r
4099 IFR_DEFAULT_DATA *DefaultId;\r
4100 IFR_DEFAULT_DATA *DefaultIdArray;\r
84f9a9ec
LG
4101 IFR_VARSTORAGE_DATA *VarStorageData;\r
4102 EFI_STRING DefaultAltCfgResp;\r
40ae09a2
ED
4103 EFI_STRING ConfigHdr;\r
4104 EFI_STRING StringPtr;\r
4105 EFI_STRING Progress;\r
40ae09a2
ED
4106\r
4107 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
4108 return EFI_INVALID_PARAMETER;\r
ae79d2f9
LG
4109 }\r
4110\r
84f9a9ec
LG
4111 //\r
4112 // Initialize the local variables.\r
4113 //\r
4114 RequestBlockArray = NULL;\r
8567300a 4115 DefaultIdArray = NULL;\r
84f9a9ec
LG
4116 VarStorageData = NULL;\r
4117 DefaultAltCfgResp = NULL;\r
40ae09a2
ED
4118 ConfigHdr = NULL;\r
4119 HiiFormPackage = NULL;\r
4120 PackageSize = 0;\r
40ae09a2
ED
4121 Progress = *Request;\r
4122\r
4123 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
84f9a9ec 4124 if (EFI_ERROR (Status)) {\r
b572d3f0 4125 goto Done;\r
84f9a9ec
LG
4126 }\r
4127\r
4128 //\r
4a429716 4129 // 1. Get the request block array by Request String when Request string contains the block array.\r
84f9a9ec
LG
4130 //\r
4131 StringPtr = NULL;\r
4132 if (*Request != NULL) {\r
ae79d2f9
LG
4133 StringPtr = *Request;\r
4134 //\r
4135 // Jump <ConfigHdr>\r
4136 //\r
4137 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4138 Status = EFI_INVALID_PARAMETER;\r
4139 goto Done;\r
4140 }\r
4141 StringPtr += StrLen (L"GUID=");\r
4142 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
4143 StringPtr++;\r
4144 }\r
4145 if (*StringPtr == L'\0') {\r
4146 Status = EFI_INVALID_PARAMETER;\r
4147 goto Done;\r
4148 }\r
4149 StringPtr += StrLen (L"&NAME=");\r
82e8c138
ED
4150 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
4151 StringPtr++;\r
6e3f5b2a 4152 }\r
82e8c138
ED
4153 if (*StringPtr == L'\0') {\r
4154 Status = EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
4155 goto Done;\r
4156 }\r
82e8c138
ED
4157 StringPtr += StrLen (L"&PATH=");\r
4158 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
4159 StringPtr ++;\r
4160 }\r
84f9a9ec 4161\r
82e8c138 4162 if (*StringPtr == L'\0') {\r
84f9a9ec 4163 //\r
82e8c138 4164 // No request block is found.\r
84f9a9ec 4165 //\r
82e8c138 4166 StringPtr = NULL;\r
84f9a9ec 4167 }\r
84f9a9ec 4168 }\r
82e8c138 4169\r
93e3992d 4170 //\r
82e8c138 4171 // If StringPtr != NULL, get the request elements.\r
93e3992d 4172 //\r
82e8c138
ED
4173 if (StringPtr != NULL) {\r
4174 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
4175 RequestBlockArray = GetBlockElement(StringPtr, &Progress);\r
4176 } else {\r
4177 RequestBlockArray = GetNameElement(StringPtr, &Progress);\r
4178 }\r
4179\r
4180 if (RequestBlockArray == NULL) {\r
4181 Status = EFI_INVALID_PARAMETER;\r
4182 goto Done;\r
84f9a9ec 4183 }\r
93e3992d 4184 }\r
82e8c138 4185\r
6e3f5b2a 4186 //\r
82e8c138 4187 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
6e3f5b2a 4188 //\r
82e8c138
ED
4189 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
4190 if (DefaultIdArray == NULL) {\r
4191 Status = EFI_OUT_OF_RESOURCES;\r
6e3f5b2a
LG
4192 goto Done;\r
4193 }\r
82e8c138 4194 InitializeListHead (&DefaultIdArray->Entry);\r
84f9a9ec 4195\r
93e3992d 4196 //\r
82e8c138 4197 // Initialize VarStorageData to store the var store Block and Default value information.\r
93e3992d 4198 //\r
82e8c138
ED
4199 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
4200 if (VarStorageData == NULL) {\r
6e3f5b2a 4201 Status = EFI_OUT_OF_RESOURCES;\r
84f9a9ec
LG
4202 goto Done;\r
4203 }\r
82e8c138
ED
4204 InitializeListHead (&VarStorageData->Entry);\r
4205 InitializeListHead (&VarStorageData->BlockEntry);\r
93e3992d 4206\r
84f9a9ec 4207 //\r
82e8c138 4208 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
84f9a9ec 4209 //\r
93e3992d 4210\r
82e8c138 4211 //\r
4a429716 4212 // Parse the opcode in form package to get the default setting.\r
82e8c138
ED
4213 //\r
4214 Status = ParseIfrData (DataBaseRecord->Handle,\r
4215 HiiFormPackage,\r
4216 (UINT32) PackageSize,\r
4217 *Request,\r
4218 RequestBlockArray,\r
4219 VarStorageData,\r
4220 DefaultIdArray);\r
4221 if (EFI_ERROR (Status)) {\r
4222 goto Done;\r
4223 }\r
84f9a9ec 4224\r
82e8c138
ED
4225 //\r
4226 // No requested varstore in IFR data and directly return\r
4227 //\r
22031c4f 4228 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {\r
82e8c138
ED
4229 Status = EFI_SUCCESS;\r
4230 goto Done;\r
4231 }\r
4232\r
4233 //\r
4234 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
4235 //\r
4236 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
4237 if (EFI_ERROR (Status)) {\r
4238 goto Done;\r
4239 }\r
4240\r
4241 if (RequestBlockArray == NULL) {\r
4242 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {\r
4243 goto Done;\r
84f9a9ec 4244 }\r
93e3992d 4245 }\r
82e8c138
ED
4246\r
4247 //\r
4248 // 4. Construct Default Value string in AltResp according to request element.\r
4249 // Go through all VarStorageData Entry and get the DefaultId array for each one\r
4250 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
4251 //\r
e68c776b 4252 Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
82e8c138
ED
4253 if (EFI_ERROR (Status)) {\r
4254 goto Done;\r
4255 }\r
93e3992d 4256\r
84f9a9ec 4257 //\r
4a429716 4258 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.\r
84f9a9ec 4259 //\r
6e3f5b2a 4260 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {\r
84f9a9ec
LG
4261 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
4262 FreePool (DefaultAltCfgResp);\r
6e3f5b2a
LG
4263 } else if (*AltCfgResp == NULL) {\r
4264 *AltCfgResp = DefaultAltCfgResp;\r
93e3992d 4265 }\r
93e3992d 4266\r
84f9a9ec
LG
4267Done:\r
4268 if (RequestBlockArray != NULL) {\r
4269 //\r
4270 // Free Link Array RequestBlockArray\r
4271 //\r
4272 while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
4273 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
4274 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
4275 if (BlockData->Name != NULL) {\r
4276 FreePool (BlockData->Name);\r
4277 }\r
84f9a9ec
LG
4278 FreePool (BlockData);\r
4279 }\r
4280\r
4281 FreePool (RequestBlockArray);\r
93e3992d 4282 }\r
82e8c138 4283\r
84f9a9ec
LG
4284 if (VarStorageData != NULL) {\r
4285 //\r
4286 // Free link array VarStorageData\r
4287 //\r
4288 while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
4289 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
4290 RemoveEntryList (&BlockData->Entry);\r
82e8c138
ED
4291 if (BlockData->Name != NULL) {\r
4292 FreePool (BlockData->Name);\r
4293 }\r
84f9a9ec
LG
4294 //\r
4295 // Free default value link array\r
4296 //\r
4297 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
4298 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
4299 RemoveEntryList (&DefaultValueData->Entry);\r
4300 FreePool (DefaultValueData);\r
4301 }\r
4302 FreePool (BlockData);\r
63d55bb9 4303 }\r
a0b0cd73
DB
4304 if (VarStorageData ->Name != NULL) {\r
4305 FreePool (VarStorageData ->Name);\r
4306 VarStorageData ->Name = NULL;\r
4307 }\r
84f9a9ec 4308 FreePool (VarStorageData);\r
93e3992d 4309 }\r
4310\r
84f9a9ec
LG
4311 if (DefaultIdArray != NULL) {\r
4312 //\r
4313 // Free DefaultId Array\r
4314 //\r
4315 while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
4316 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
4317 RemoveEntryList (&DefaultId->Entry);\r
4318 FreePool (DefaultId);\r
4319 }\r
4320 FreePool (DefaultIdArray);\r
4321 }\r
82e8c138 4322\r
84f9a9ec
LG
4323 //\r
4324 // Free the allocated string \r
4325 //\r
84f9a9ec
LG
4326 if (ConfigHdr != NULL) {\r
4327 FreePool (ConfigHdr);\r
4328 }\r
93e3992d 4329\r
84f9a9ec 4330 //\r
4a429716 4331 // Free Package data\r
84f9a9ec 4332 //\r
8567300a
LG
4333 if (HiiFormPackage != NULL) {\r
4334 FreePool (HiiFormPackage);\r
676df92c 4335 }\r
63d55bb9 4336\r
ae79d2f9
LG
4337 if (PointerProgress != NULL) {\r
4338 if (*Request == NULL) {\r
4339 *PointerProgress = NULL;\r
4340 } else if (EFI_ERROR (Status)) {\r
82e8c138 4341 *PointerProgress = *Request;\r
ae79d2f9
LG
4342 } else {\r
4343 *PointerProgress = *Request + StrLen (*Request);\r
4344 }\r
4345 }\r
4346\r
93e3992d 4347 return Status;\r
4348}\r
4349\r
cce6230f
ED
4350/**\r
4351 This function gets the full request resp string by \r
4352 parsing IFR data in HII form packages.\r
4353\r
4354 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4355 instance.\r
4356 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
4357 varstore data structure. \r
4358 @param Request Pointer to a null-terminated Unicode string in\r
4359 <ConfigRequest> format.\r
4360 @param RequestResp Pointer to a null-terminated Unicode string in\r
4361 <ConfigResp> format.\r
4362 @param AccessProgress On return, points to a character in the Request\r
4363 string. Points to the string's null terminator if\r
4364 request was successful. Points to the most recent\r
4365 & before the first failing name / value pair (or\r
4366 the beginning of the string if the failure is in\r
4367 the first name / value pair) if the request was\r
4368 not successful.\r
4369\r
4370 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4371 And AltCfgResp contains all default value string.\r
4372 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
4373 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
4374\r
4375**/\r
4376EFI_STATUS\r
4377GetConfigRespFromEfiVarStore (\r
4378 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4379 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
4380 IN EFI_STRING Request,\r
4381 OUT EFI_STRING *RequestResp,\r
4382 OUT EFI_STRING *AccessProgress\r
4383 )\r
4384{\r
4385 EFI_STATUS Status;\r
4386 EFI_STRING VarStoreName;\r
b68ccac1 4387 UINTN NameSize;\r
cce6230f
ED
4388 UINT8 *VarStore;\r
4389 UINTN BufferSize;\r
4390\r
7248790e
ED
4391 Status = EFI_SUCCESS;\r
4392 BufferSize = 0;\r
4393 VarStore = NULL;\r
4394 VarStoreName = NULL;\r
4395 *AccessProgress = Request;\r
b68ccac1
SZ
4396\r
4397 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
4398 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
cce6230f
ED
4399 if (VarStoreName == NULL) {\r
4400 Status = EFI_OUT_OF_RESOURCES;\r
4401 goto Done;\r
4402 }\r
b68ccac1 4403 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
cce6230f
ED
4404 \r
4405 \r
4406 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
4407 if (Status != EFI_BUFFER_TOO_SMALL) {\r
4408 goto Done;\r
4409 }\r
4410\r
4411 VarStore = AllocateZeroPool (BufferSize);\r
4412 ASSERT (VarStore != NULL);\r
4413 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
4414 if (EFI_ERROR (Status)) {\r
4415 goto Done;\r
4416 }\r
4417\r
4418 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
4419 if (EFI_ERROR (Status)) {\r
4420 goto Done;\r
4421 }\r
4422\r
4423Done:\r
4424 if (VarStoreName != NULL) {\r
4425 FreePool (VarStoreName);\r
4426 }\r
4427\r
4428 if (VarStore != NULL) {\r
4429 FreePool (VarStore);\r
4430 }\r
4431\r
4432 return Status;\r
4433}\r
4434\r
4435\r
4436/**\r
4437 This function route the full request resp string for efi varstore. \r
4438\r
4439 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4440 instance.\r
4441 @param EfiVarStoreInfo The efi varstore info which is save in the EFI \r
4442 varstore data structure. \r
4443 @param RequestResp Pointer to a null-terminated Unicode string in\r
4444 <ConfigResp> format.\r
4445 @param Result Pointer to a null-terminated Unicode string in\r
4446 <ConfigResp> format.\r
4447 \r
4448 @retval EFI_SUCCESS The Results string is set to the full request string.\r
4449 And AltCfgResp contains all default value string.\r
4450 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
4451 @retval EFI_INVALID_PARAMETER Request points to NULL.\r
4452\r
4453**/\r
4454EFI_STATUS\r
4455RouteConfigRespForEfiVarStore (\r
4456 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4457 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, \r
4458 IN EFI_STRING RequestResp,\r
4459 OUT EFI_STRING *Result\r
4460 )\r
4461{\r
4462 EFI_STATUS Status;\r
4463 EFI_STRING VarStoreName;\r
b68ccac1 4464 UINTN NameSize;\r
f26b6a9c 4465 UINT8 *VarStore;\r
cce6230f
ED
4466 UINTN BufferSize;\r
4467 UINTN BlockSize;\r
4468\r
4469 Status = EFI_SUCCESS;\r
4470 BufferSize = 0;\r
4471 VarStore = NULL;\r
4472 VarStoreName = NULL;\r
237e849d 4473 *Result = RequestResp;\r
cce6230f 4474\r
b68ccac1
SZ
4475 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
4476 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
cce6230f
ED
4477 if (VarStoreName == NULL) {\r
4478 Status = EFI_OUT_OF_RESOURCES;\r
4479 goto Done;\r
4480 }\r
b68ccac1 4481 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
cce6230f
ED
4482 \r
4483 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
4484 if (Status != EFI_BUFFER_TOO_SMALL) {\r
237e849d 4485 DEBUG ((DEBUG_ERROR, "The variable does not exist!"));\r
cce6230f
ED
4486 goto Done;\r
4487 }\r
4488\r
4489 BlockSize = BufferSize;\r
4490 VarStore = AllocateZeroPool (BufferSize);\r
4491 ASSERT (VarStore != NULL);\r
4492 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
4493 if (EFI_ERROR (Status)) {\r
4494 goto Done;\r
4495 }\r
4496\r
4497 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);\r
4498 if (EFI_ERROR (Status)) {\r
4499 goto Done;\r
4500 }\r
4501\r
4502 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
4503 if (EFI_ERROR (Status)) {\r
237e849d 4504 *Result = RequestResp;\r
cce6230f
ED
4505 goto Done;\r
4506 }\r
4507\r
4508Done:\r
4509 if (VarStoreName != NULL) {\r
4510 FreePool (VarStoreName);\r
4511 }\r
4512\r
4513 if (VarStore != NULL) {\r
4514 FreePool (VarStore);\r
4515 }\r
4516\r
4517 return Status;\r
4518}\r
4519\r
82e8c138
ED
4520/**\r
4521 Validate the config request elements.\r
4522\r
4523 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
4524 without configHdr field.\r
4525\r
4526 @retval CHAR16 * THE first Name/value pair not correct.\r
4527 @retval NULL Success parse the name/value pair\r
4528**/\r
4529CHAR16 *\r
4530OffsetWidthValidate (\r
4531 CHAR16 *ConfigElements\r
4532 )\r
4533{\r
4534 CHAR16 *StringPtr;\r
4535 CHAR16 *RetVal;\r
4536\r
4537 StringPtr = ConfigElements;\r
4538\r
4539 while (1) {\r
4540 RetVal = StringPtr;\r
4541 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
4542 return RetVal;\r
4543 }\r
4544\r
4545 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
4546 StringPtr++;\r
4547 }\r
4548 if (*StringPtr == L'\0') {\r
4549 return RetVal;\r
4550 }\r
4551\r
4552 StringPtr += StrLen (L"&WIDTH=");\r
4553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
4554 StringPtr ++;\r
4555 }\r
4556\r
4557 if (*StringPtr == L'\0') {\r
4558 return NULL;\r
4559 }\r
4560 }\r
4561}\r
4562\r
4563/**\r
4564 Validate the config request elements.\r
4565\r
4566 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format, \r
4567 without configHdr field.\r
4568\r
4569 @retval CHAR16 * THE first Name/value pair not correct.\r
4570 @retval NULL Success parse the name/value pair\r
4571\r
4572**/\r
4573CHAR16 *\r
4574NameValueValidate (\r
4575 CHAR16 *ConfigElements\r
4576 )\r
4577{\r
4578 CHAR16 *StringPtr;\r
4579 CHAR16 *RetVal;\r
4580\r
4581 StringPtr = ConfigElements;\r
4582\r
4583 while (1) {\r
4584 RetVal = StringPtr;\r
4585 if (*StringPtr != L'&') {\r
4586 return RetVal;\r
4587 }\r
4588 StringPtr += 1;\r
4589\r
4590 StringPtr = StrStr (StringPtr, L"&");\r
4591 \r
4592 if (StringPtr == NULL) {\r
4593 return NULL;\r
4594 }\r
4595 }\r
4596}\r
4597\r
4598/**\r
4599 Validate the config request string.\r
4600\r
4601 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
4602\r
4603 @retval CHAR16 * THE first element not correct.\r
4604 @retval NULL Success parse the name/value pair\r
4605\r
4606**/\r
4607CHAR16 *\r
4608ConfigRequestValidate (\r
4609 CHAR16 *ConfigRequest\r
4610 )\r
4611{\r
4612 BOOLEAN HasNameField;\r
4613 CHAR16 *StringPtr;\r
4614\r
4615 HasNameField = TRUE;\r
4616 StringPtr = ConfigRequest;\r
4617\r
4618 //\r
4619 // Check <ConfigHdr>\r
4620 //\r
4621 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4622 return ConfigRequest;\r
4623 }\r
4624 StringPtr += StrLen (L"GUID=");\r
4625 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
4626 StringPtr++;\r
4627 }\r
4628 if (*StringPtr == L'\0') {\r
4629 return ConfigRequest;\r
4630 }\r
4631 StringPtr += StrLen (L"&NAME=");\r
4632 if (*StringPtr == L'&') {\r
4633 HasNameField = FALSE;\r
4634 }\r
4635 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
4636 StringPtr++;\r
4637 }\r
4638 if (*StringPtr == L'\0') {\r
4639 return ConfigRequest;\r
4640 }\r
4641 StringPtr += StrLen (L"&PATH=");\r
4642 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
4643 StringPtr ++;\r
4644 }\r
4645\r
4646 if (*StringPtr == L'\0') {\r
4647 return NULL;\r
4648 }\r
4649\r
4650 if (HasNameField) {\r
4651 //\r
4652 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
4653 //\r
4654 return OffsetWidthValidate(StringPtr);\r
4655 } else {\r
4656 //\r
4657 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
4658 //\r
4659 return NameValueValidate(StringPtr);\r
4660 }\r
4661}\r
4662\r
93e3992d 4663/**\r
4664 This function allows a caller to extract the current configuration\r
4665 for one or more named elements from one or more drivers.\r
4666\r
4667 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
4668 instance.\r
4669 @param Request A null-terminated Unicode string in\r
4670 <MultiConfigRequest> format.\r
4671 @param Progress On return, points to a character in the Request\r
4672 string. Points to the string's null terminator if\r
4673 request was successful. Points to the most recent\r
4674 & before the first failing name / value pair (or\r
4675 the beginning of the string if the failure is in\r
4676 the first name / value pair) if the request was\r
4677 not successful.\r
4678 @param Results Null-terminated Unicode string in\r
4679 <MultiConfigAltResp> format which has all values\r
4680 filled in for the names in the Request string.\r
4681 String to be allocated by the called function.\r
4682\r
4683 @retval EFI_SUCCESS The Results string is filled with the values\r
4684 corresponding to all requested names.\r
4685 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
4686 results that must be stored awaiting possible\r
4687 future protocols.\r
4688 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
4689 Progress set to the "G" in "GUID" of the routing\r
4690 header that doesn't match. Note: There is no\r
4691 requirement that all routing data be validated\r
4692 before any configuration extraction.\r
4693 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
4694 parameter would result in this type of error. The\r
4695 Progress parameter is set to NULL.\r
4696 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
4697 before the error or the beginning of the string.\r
46c3efbb
ED
4698 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII\r
4699 Configuration Access Protocol returned \r
4700 EFI_INVALID_PARAMETER. Progress set to most recent\r
4701 & before the error or the beginning of the string.\r
93e3992d 4702\r
4703**/\r
4704EFI_STATUS\r
4705EFIAPI\r
4706HiiConfigRoutingExtractConfig (\r
4707 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
4708 IN CONST EFI_STRING Request,\r
4709 OUT EFI_STRING *Progress,\r
4710 OUT EFI_STRING *Results\r
4711 )\r
4712{\r
84f9a9ec 4713 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 4714 EFI_STRING StringPtr;\r
4715 EFI_STRING ConfigRequest;\r
4716 UINTN Length;\r
4717 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 4718 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 4719 EFI_STATUS Status;\r
84f9a9ec
LG
4720 LIST_ENTRY *Link;\r
4721 HII_DATABASE_RECORD *Database;\r
4722 UINT8 *DevicePathPkg;\r
4723 UINT8 *CurrentDevicePath;\r
93e3992d 4724 EFI_HANDLE DriverHandle;\r
84f9a9ec 4725 EFI_HII_HANDLE HiiHandle;\r
93e3992d 4726 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
4727 EFI_STRING AccessProgress;\r
4728 EFI_STRING AccessResults;\r
74e8963c
DB
4729 EFI_STRING AccessProgressBackup;\r
4730 EFI_STRING AccessResultsBackup;\r
84f9a9ec 4731 EFI_STRING DefaultResults;\r
8d00a0f1 4732 BOOLEAN FirstElement;\r
6e3f5b2a 4733 BOOLEAN IfrDataParsedFlag;\r
cce6230f 4734 BOOLEAN IsEfiVarStore;\r
82e8c138
ED
4735 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
4736 EFI_STRING ErrorPtr;\r
7248790e 4737 UINTN DevicePathSize;\r
74e8963c
DB
4738 UINTN ConigStringSize;\r
4739 UINTN ConigStringSizeNewsize;\r
4740 EFI_STRING ConfigStringPtr;\r
93e3992d 4741\r
4742 if (This == NULL || Progress == NULL || Results == NULL) {\r
4743 return EFI_INVALID_PARAMETER;\r
4744 }\r
4745\r
4746 if (Request == NULL) {\r
4747 *Progress = NULL;\r
4748 return EFI_INVALID_PARAMETER;\r
4749 }\r
4750\r
84f9a9ec 4751 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 4752 StringPtr = Request;\r
4753 *Progress = StringPtr;\r
84f9a9ec
LG
4754 DefaultResults = NULL;\r
4755 ConfigRequest = NULL;\r
4756 Status = EFI_SUCCESS;\r
4757 AccessResults = NULL;\r
cce6230f 4758 AccessProgress = NULL;\r
74e8963c
DB
4759 AccessResultsBackup = NULL;\r
4760 AccessProgressBackup = NULL;\r
84f9a9ec 4761 DevicePath = NULL;\r
6e3f5b2a 4762 IfrDataParsedFlag = FALSE;\r
cce6230f
ED
4763 IsEfiVarStore = FALSE;\r
4764 EfiVarStoreInfo = NULL;\r
93e3992d 4765\r
4766 //\r
4767 // The first element of <MultiConfigRequest> should be\r
4768 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
4769 //\r
4770 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
4771 return EFI_INVALID_PARAMETER;\r
4772 }\r
4773\r
8d00a0f1 4774 FirstElement = TRUE;\r
4775\r
93e3992d 4776 //\r
4777 // Allocate a fix length of memory to store Results. Reallocate memory for\r
4778 // Results if this fix length is insufficient.\r
4779 //\r
4780 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
4781 if (*Results == NULL) {\r
4782 return EFI_OUT_OF_RESOURCES;\r
4783 }\r
4784\r
4785 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
4786 //\r
4787 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
4788 // or most recent & before the error.\r
4789 //\r
4790 if (StringPtr == Request) {\r
4791 *Progress = StringPtr;\r
4792 } else {\r
4793 *Progress = StringPtr - 1;\r
4794 }\r
4795\r
4796 //\r
4797 // Process each <ConfigRequest> of <MultiConfigRequest>\r
4798 //\r
4799 Length = CalculateConfigStringLen (StringPtr);\r
4800 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
4801 if (ConfigRequest == NULL) {\r
84f9a9ec
LG
4802 Status = EFI_OUT_OF_RESOURCES;\r
4803 goto Done;\r
93e3992d 4804 }\r
4805 *(ConfigRequest + Length) = 0;\r
4806\r
4807 //\r
4808 // Get the UEFI device path\r
4809 //\r
4810 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
4811 if (EFI_ERROR (Status)) {\r
84f9a9ec 4812 goto Done;\r
93e3992d 4813 }\r
4814\r
4815 //\r
84f9a9ec
LG
4816 // Find driver which matches the routing data.\r
4817 //\r
4818 DriverHandle = NULL;\r
4819 HiiHandle = NULL;\r
8567300a 4820 Database = NULL;\r
84f9a9ec
LG
4821 for (Link = Private->DatabaseList.ForwardLink;\r
4822 Link != &Private->DatabaseList;\r
4823 Link = Link->ForwardLink\r
4824 ) {\r
4825 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
84f9a9ec
LG
4826 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
4827 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
7248790e 4828 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
8aaab674 4829 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {\r
84f9a9ec
LG
4830 DriverHandle = Database->DriverHandle;\r
4831 HiiHandle = Database->Handle;\r
4832 break;\r
4833 }\r
4834 }\r
4835 }\r
4836 \r
4837 //\r
4838 // Try to find driver handle by device path.\r
93e3992d 4839 //\r
84f9a9ec
LG
4840 if (DriverHandle == NULL) {\r
4841 TempDevicePath = DevicePath;\r
4842 Status = gBS->LocateDevicePath (\r
4843 &gEfiDevicePathProtocolGuid,\r
4844 &TempDevicePath,\r
4845 &DriverHandle\r
4846 );\r
4847 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
4848 //\r
4849 // Routing data does not match any known driver.\r
4850 // Set Progress to the 'G' in "GUID" of the routing header.\r
4851 //\r
4852 *Progress = StringPtr;\r
4853 Status = EFI_NOT_FOUND;\r
4854 goto Done;\r
4855 }\r
4856 }\r
82e8c138
ED
4857\r
4858 //\r
4859 // Validate ConfigRequest String.\r
4860 //\r
4861 ErrorPtr = ConfigRequestValidate(ConfigRequest);\r
4862 if (ErrorPtr != NULL) {\r
4863 *Progress = StrStr (StringPtr, ErrorPtr);\r
4864 Status = EFI_INVALID_PARAMETER;\r
4865 goto Done;\r
4866 }\r
4867\r
84f9a9ec 4868 //\r
82e8c138 4869 // Check whether ConfigRequest contains request string.\r
84f9a9ec 4870 //\r
6e3f5b2a 4871 IfrDataParsedFlag = FALSE;\r
82e8c138 4872 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {\r
93e3992d 4873 //\r
84f9a9ec 4874 // Get the full request string from IFR when HiiPackage is registered to HiiHandle \r
93e3992d 4875 //\r
6e3f5b2a 4876 IfrDataParsedFlag = TRUE;\r
ae79d2f9 4877 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
84f9a9ec 4878 if (EFI_ERROR (Status)) {\r
ae79d2f9
LG
4879 //\r
4880 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
4881 // Map it to the progress on <MultiConfigRequest> then return it.\r
4882 //\r
82e8c138 4883 ASSERT (AccessProgress != NULL);\r
ae79d2f9 4884 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec
LG
4885 goto Done;\r
4886 }\r
1f1cb2f2
LG
4887 //\r
4888 // Not any request block is found.\r
4889 //\r
82e8c138 4890 if (!GetElementsFromRequest(ConfigRequest)) {\r
76c24251 4891 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
1f1cb2f2
LG
4892 goto NextConfigString;\r
4893 }\r
93e3992d 4894 }\r
4895\r
4896 //\r
cce6230f 4897 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 4898 //\r
cce6230f
ED
4899 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
4900 if (EFI_ERROR (Status)) {\r
4901 goto Done;\r
4902 }\r
4903 \r
4904 if (IsEfiVarStore) {\r
4905 //\r
4906 // Call the GetVariable function to extract settings.\r
4907 //\r
4908 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
82e8c138 4909 FreePool (EfiVarStoreInfo);\r
74e8963c
DB
4910 if (EFI_ERROR (Status)) {\r
4911 //\r
4912 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
4913 // Map it to the progress on <MultiConfigRequest> then return it.\r
4914 //\r
4915 *Progress = StrStr (StringPtr, AccessProgress);\r
4916 goto Done;\r
4917 }\r
4918\r
4919 //\r
4920 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.\r
4921 //\r
4922 Status = gBS->HandleProtocol (\r
4923 DriverHandle,\r
4924 &gEfiHiiConfigAccessProtocolGuid,\r
4925 (VOID **) &ConfigAccess\r
4926 );\r
4927 if (EFI_ERROR (Status)) {\r
4928 //\r
4929 // The driver has EfiVarStore, may not install ConfigAccess protocol.\r
4930 // So ignore the error status in this case.\r
4931 //\r
4932 Status = EFI_SUCCESS;\r
4933 } else {\r
4934 Status = ConfigAccess->ExtractConfig (\r
4935 ConfigAccess,\r
4936 ConfigRequest,\r
4937 &AccessProgressBackup,\r
4938 &AccessResultsBackup\r
4939 );\r
4940 if (!EFI_ERROR(Status)) {\r
4941 //\r
4942 //Merge the AltCfgResp in AccessResultsBackup to AccessResults\r
4943 //\r
4944 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {\r
4945 ConigStringSize = StrSize (AccessResults);\r
4946 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");\r
4947 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);\r
4948 AccessResults = (EFI_STRING) ReallocatePool (\r
4949 ConigStringSize,\r
4950 ConigStringSizeNewsize,\r
4951 AccessResults);\r
4952 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);\r
4953 }\r
4954 } else {\r
4955 //\r
4956 // In the ExtractConfig function of some driver may not support EfiVarStore,\r
4957 // may return error status, just ignore the error status in this case.\r
4958 //\r
4959 Status = EFI_SUCCESS;\r
4960 }\r
4961 if (AccessResultsBackup != NULL) {\r
4962 FreePool (AccessResultsBackup);\r
4963 AccessResultsBackup = NULL;\r
4964 }\r
4965 }\r
cce6230f
ED
4966 } else {\r
4967 //\r
4968 // Call corresponding ConfigAccess protocol to extract settings\r
4969 //\r
4970 Status = gBS->HandleProtocol (\r
4971 DriverHandle,\r
4972 &gEfiHiiConfigAccessProtocolGuid,\r
4973 (VOID **) &ConfigAccess\r
4974 );\r
a115a9ef
EC
4975 if (EFI_ERROR (Status)) {\r
4976 goto Done;\r
4977 }\r
93e3992d 4978\r
cce6230f
ED
4979 Status = ConfigAccess->ExtractConfig (\r
4980 ConfigAccess,\r
4981 ConfigRequest,\r
4982 &AccessProgress,\r
4983 &AccessResults\r
4984 );\r
4985 }\r
93e3992d 4986 if (EFI_ERROR (Status)) {\r
4987 //\r
4988 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
4989 // Map it to the progress on <MultiConfigRequest> then return it.\r
4990 //\r
8d00a0f1 4991 *Progress = StrStr (StringPtr, AccessProgress);\r
84f9a9ec 4992 goto Done;\r
93e3992d 4993 }\r
4994\r
4995 //\r
8d00a0f1 4996 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4a429716 4997 // which separates the first <ConfigAltResp> and the following ones.\r
93e3992d 4998 //\r
4999 ASSERT (*AccessProgress == 0);\r
8d00a0f1 5000\r
84f9a9ec
LG
5001 //\r
5002 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
5003 //\r
ae79d2f9
LG
5004 if (!IfrDataParsedFlag && HiiHandle != NULL) {\r
5005 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
5006 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 5007 }\r
ae79d2f9 5008\r
84f9a9ec
LG
5009 FreePool (DevicePath);\r
5010 DevicePath = NULL;\r
84f9a9ec 5011\r
ae79d2f9
LG
5012 if (DefaultResults != NULL) {\r
5013 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
5014 ASSERT_EFI_ERROR (Status);\r
5015 FreePool (DefaultResults);\r
5016 DefaultResults = NULL;\r
5017 }\r
5018 \r
82e8c138 5019NextConfigString:\r
8d00a0f1 5020 if (!FirstElement) {\r
5021 Status = AppendToMultiString (Results, L"&");\r
5022 ASSERT_EFI_ERROR (Status);\r
5023 }\r
5024 \r
93e3992d 5025 Status = AppendToMultiString (Results, AccessResults);\r
5026 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 5027\r
5028 FirstElement = FALSE;\r
84f9a9ec 5029\r
676df92c 5030 FreePool (AccessResults);\r
93e3992d 5031 AccessResults = NULL;\r
676df92c 5032 FreePool (ConfigRequest);\r
93e3992d 5033 ConfigRequest = NULL;\r
5034\r
5035 //\r
5036 // Go to next <ConfigRequest> (skip '&').\r
5037 //\r
5038 StringPtr += Length;\r
5039 if (*StringPtr == 0) {\r
5040 *Progress = StringPtr;\r
5041 break;\r
5042 }\r
5043\r
5044 StringPtr++;\r
93e3992d 5045 }\r
5046\r
84f9a9ec
LG
5047Done:\r
5048 if (EFI_ERROR (Status)) {\r
5049 FreePool (*Results);\r
6e3f5b2a 5050 *Results = NULL;\r
84f9a9ec
LG
5051 }\r
5052 \r
5053 if (ConfigRequest != NULL) {\r
5054 FreePool (ConfigRequest);\r
5055 }\r
5056 \r
5057 if (AccessResults != NULL) {\r
5058 FreePool (AccessResults);\r
5059 }\r
5060 \r
5061 if (DefaultResults != NULL) {\r
5062 FreePool (DefaultResults);\r
5063 }\r
5064 \r
5065 if (DevicePath != NULL) {\r
5066 FreePool (DevicePath);\r
5067 } \r
93e3992d 5068\r
84f9a9ec 5069 return Status;\r
93e3992d 5070}\r
5071\r
5072\r
5073/**\r
5074 This function allows the caller to request the current configuration for the\r
5075 entirety of the current HII database and returns the data in a\r
5076 null-terminated Unicode string.\r
5077\r
5078 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5079 instance.\r
5080 @param Results Null-terminated Unicode string in\r
5081 <MultiConfigAltResp> format which has all values\r
c0a3c3da
ED
5082 filled in for the entirety of the current HII \r
5083 database. String to be allocated by the called \r
5084 function. De-allocation is up to the caller.\r
93e3992d 5085\r
5086 @retval EFI_SUCCESS The Results string is filled with the values\r
5087 corresponding to all requested names.\r
5088 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
5089 results that must be stored awaiting possible\r
5090 future protocols.\r
5091 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
5092 parameter would result in this type of error.\r
5093\r
5094**/\r
5095EFI_STATUS\r
5096EFIAPI\r
5097HiiConfigRoutingExportConfig (\r
5098 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5099 OUT EFI_STRING *Results\r
5100 )\r
5101{\r
93e3992d 5102 EFI_STATUS Status;\r
93e3992d 5103 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
84f9a9ec
LG
5104 EFI_STRING AccessResults;\r
5105 EFI_STRING Progress;\r
6e3f5b2a 5106 EFI_STRING StringPtr;\r
ae79d2f9 5107 EFI_STRING ConfigRequest;\r
8d00a0f1 5108 UINTN Index;\r
5109 EFI_HANDLE *ConfigAccessHandles;\r
5110 UINTN NumberConfigAccessHandles;\r
5111 BOOLEAN FirstElement;\r
84f9a9ec
LG
5112 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
5113 EFI_HII_HANDLE HiiHandle;\r
5114 EFI_STRING DefaultResults;\r
5115 HII_DATABASE_PRIVATE_DATA *Private;\r
5116 LIST_ENTRY *Link;\r
5117 HII_DATABASE_RECORD *Database;\r
5118 UINT8 *DevicePathPkg;\r
5119 UINT8 *CurrentDevicePath;\r
ae79d2f9 5120 BOOLEAN IfrDataParsedFlag;\r
93e3992d 5121\r
5122 if (This == NULL || Results == NULL) {\r
5123 return EFI_INVALID_PARAMETER;\r
5124 }\r
5125\r
84f9a9ec
LG
5126 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5127\r
93e3992d 5128 //\r
5129 // Allocate a fix length of memory to store Results. Reallocate memory for\r
5130 // Results if this fix length is insufficient.\r
5131 //\r
5132 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
5133 if (*Results == NULL) {\r
5134 return EFI_OUT_OF_RESOURCES;\r
5135 }\r
5136\r
8d00a0f1 5137 NumberConfigAccessHandles = 0;\r
5138 Status = gBS->LocateHandleBuffer (\r
5139 ByProtocol,\r
5140 &gEfiHiiConfigAccessProtocolGuid,\r
5141 NULL,\r
5142 &NumberConfigAccessHandles,\r
5143 &ConfigAccessHandles\r
5144 );\r
5145 if (EFI_ERROR (Status)) {\r
5146 return Status;\r
5147 }\r
93e3992d 5148\r
8d00a0f1 5149 FirstElement = TRUE;\r
93e3992d 5150\r
8d00a0f1 5151 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 5152 Status = gBS->HandleProtocol (\r
8d00a0f1 5153 ConfigAccessHandles[Index],\r
93e3992d 5154 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 5155 (VOID **) &ConfigAccess\r
93e3992d 5156 );\r
8d00a0f1 5157 if (EFI_ERROR (Status)) {\r
5158 continue;\r
5159 }\r
93e3992d 5160\r
84f9a9ec
LG
5161 //\r
5162 // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
5163 //\r
ae79d2f9 5164 IfrDataParsedFlag = FALSE;\r
84f9a9ec
LG
5165 Progress = NULL;\r
5166 HiiHandle = NULL;\r
84f9a9ec 5167 DefaultResults = NULL;\r
8567300a 5168 Database = NULL;\r
ae79d2f9 5169 ConfigRequest = NULL;\r
84f9a9ec 5170 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
84f9a9ec
LG
5171 if (DevicePath != NULL) {\r
5172 for (Link = Private->DatabaseList.ForwardLink;\r
5173 Link != &Private->DatabaseList;\r
5174 Link = Link->ForwardLink\r
5175 ) {\r
5176 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
5177 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
5178 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
6e3f5b2a 5179 if (CompareMem (\r
84f9a9ec
LG
5180 DevicePath,\r
5181 CurrentDevicePath,\r
6e3f5b2a
LG
5182 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
5183 ) == 0) {\r
84f9a9ec
LG
5184 HiiHandle = Database->Handle;\r
5185 break;\r
5186 }\r
5187 }\r
5188 }\r
5189 }\r
5190\r
93e3992d 5191 Status = ConfigAccess->ExtractConfig (\r
5192 ConfigAccess,\r
6e3f5b2a 5193 NULL,\r
84f9a9ec 5194 &Progress,\r
93e3992d 5195 &AccessResults\r
5196 );\r
ae79d2f9 5197 if (EFI_ERROR (Status)) {\r
6e3f5b2a
LG
5198 //\r
5199 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
5200 //\r
5201 if (HiiHandle != NULL && DevicePath != NULL) {\r
ae79d2f9
LG
5202 IfrDataParsedFlag = TRUE;\r
5203 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
5204 //\r
5205 // Get the full request string to get the Current setting again.\r
5206 //\r
5207 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {\r
5208 Status = ConfigAccess->ExtractConfig (\r
5209 ConfigAccess,\r
5210 ConfigRequest,\r
5211 &Progress,\r
5212 &AccessResults\r
5213 );\r
5214 FreePool (ConfigRequest);\r
5215 } else {\r
5216 Status = EFI_NOT_FOUND;\r
5217 }\r
5218 }\r
5219 }\r
5220\r
5221 if (!EFI_ERROR (Status)) {\r
5222 //\r
5223 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle \r
5224 //\r
5225 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {\r
6e3f5b2a
LG
5226 StringPtr = StrStr (AccessResults, L"&GUID=");\r
5227 if (StringPtr != NULL) {\r
5228 *StringPtr = 0;\r
5229 }\r
82e8c138 5230 if (GetElementsFromRequest (AccessResults)) {\r
ae79d2f9
LG
5231 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
5232 ASSERT_EFI_ERROR (Status);\r
6e3f5b2a
LG
5233 }\r
5234 if (StringPtr != NULL) {\r
5235 *StringPtr = L'&';\r
5236 }\r
5237 }\r
84f9a9ec
LG
5238 //\r
5239 // Merge the default sting from IFR code into the got setting from driver.\r
5240 //\r
5241 if (DefaultResults != NULL) {\r
8567300a
LG
5242 Status = MergeDefaultString (&AccessResults, DefaultResults);\r
5243 ASSERT_EFI_ERROR (Status);\r
84f9a9ec 5244 FreePool (DefaultResults);\r
8567300a 5245 DefaultResults = NULL;\r
84f9a9ec
LG
5246 }\r
5247 \r
8d00a0f1 5248 //\r
5249 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
4a429716 5250 // which separates the first <ConfigAltResp> and the following ones.\r
8d00a0f1 5251 //\r
5252 if (!FirstElement) {\r
5253 Status = AppendToMultiString (Results, L"&");\r
5254 ASSERT_EFI_ERROR (Status);\r
676df92c 5255 }\r
8d00a0f1 5256 \r
5257 Status = AppendToMultiString (Results, AccessResults);\r
5258 ASSERT_EFI_ERROR (Status);\r
93e3992d 5259\r
8d00a0f1 5260 FirstElement = FALSE;\r
5261 \r
5262 FreePool (AccessResults);\r
5263 AccessResults = NULL;\r
5264 }\r
93e3992d 5265 }\r
f4113e1f 5266 FreePool (ConfigAccessHandles);\r
93e3992d 5267\r
8d00a0f1 5268 return EFI_SUCCESS; \r
93e3992d 5269}\r
5270\r
5271\r
5272/**\r
5273 This function processes the results of processing forms and routes it to the\r
5274 appropriate handlers or storage.\r
5275\r
5276 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5277 instance.\r
5278 @param Configuration A null-terminated Unicode string in\r
5279 <MulltiConfigResp> format.\r
5280 @param Progress A pointer to a string filled in with the offset of\r
5281 the most recent & before the first failing name /\r
5282 value pair (or the beginning of the string if the\r
5283 failure is in the first name / value pair) or the\r
5284 terminating NULL if all was successful.\r
5285\r
5286 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
5287 distribution.\r
5288 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
5289 results that must be stored awaiting possible\r
5290 future protocols.\r
5291 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
5292 would result in this type of error.\r
5293 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
5294 found.\r
5295\r
5296**/\r
5297EFI_STATUS\r
5298EFIAPI\r
813acf3a 5299HiiConfigRoutingRouteConfig (\r
93e3992d 5300 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5301 IN CONST EFI_STRING Configuration,\r
5302 OUT EFI_STRING *Progress\r
5303 )\r
5304{\r
84f9a9ec 5305 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 5306 EFI_STRING StringPtr;\r
5307 EFI_STRING ConfigResp;\r
5308 UINTN Length;\r
5309 EFI_STATUS Status;\r
5310 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 5311 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
84f9a9ec
LG
5312 LIST_ENTRY *Link;\r
5313 HII_DATABASE_RECORD *Database;\r
5314 UINT8 *DevicePathPkg;\r
5315 UINT8 *CurrentDevicePath;\r
93e3992d 5316 EFI_HANDLE DriverHandle;\r
5317 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
5318 EFI_STRING AccessProgress;\r
cce6230f
ED
5319 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
5320 BOOLEAN IsEfiVarstore;\r
7248790e 5321 UINTN DevicePathSize;\r
93e3992d 5322\r
5323 if (This == NULL || Progress == NULL) {\r
5324 return EFI_INVALID_PARAMETER;\r
5325 }\r
5326\r
5327 if (Configuration == NULL) {\r
5328 *Progress = NULL;\r
5329 return EFI_INVALID_PARAMETER;\r
5330 }\r
5331\r
84f9a9ec 5332 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
93e3992d 5333 StringPtr = Configuration;\r
5334 *Progress = StringPtr;\r
cce6230f
ED
5335 Database = NULL;\r
5336 AccessProgress = NULL;\r
5337 EfiVarStoreInfo= NULL;\r
5338 IsEfiVarstore = FALSE;\r
93e3992d 5339\r
5340 //\r
5341 // The first element of <MultiConfigResp> should be\r
5342 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
5343 //\r
5344 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
5345 return EFI_INVALID_PARAMETER;\r
5346 }\r
5347\r
5348 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
5349 //\r
5350 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
5351 // or most recent & before the error.\r
5352 //\r
5353 if (StringPtr == Configuration) {\r
5354 *Progress = StringPtr;\r
5355 } else {\r
5356 *Progress = StringPtr - 1;\r
5357 }\r
5358\r
5359 //\r
5360 // Process each <ConfigResp> of <MultiConfigResp>\r
5361 //\r
5362 Length = CalculateConfigStringLen (StringPtr);\r
5363 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
5364 if (ConfigResp == NULL) {\r
5365 return EFI_OUT_OF_RESOURCES;\r
5366 }\r
5367 //\r
5368 // Append '\0' to the end of ConfigRequest\r
5369 //\r
5370 *(ConfigResp + Length) = 0;\r
5371\r
5372 //\r
5373 // Get the UEFI device path\r
5374 //\r
5375 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
5376 if (EFI_ERROR (Status)) {\r
676df92c 5377 FreePool (ConfigResp);\r
93e3992d 5378 return Status;\r
5379 }\r
5380\r
5381 //\r
84f9a9ec
LG
5382 // Find driver which matches the routing data.\r
5383 //\r
5384 DriverHandle = NULL;\r
84f9a9ec
LG
5385 for (Link = Private->DatabaseList.ForwardLink;\r
5386 Link != &Private->DatabaseList;\r
5387 Link = Link->ForwardLink\r
5388 ) {\r
5389 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
5390\r
5391 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
5392 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
7248790e 5393 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
8aaab674 5394 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {\r
84f9a9ec
LG
5395 DriverHandle = Database->DriverHandle;\r
5396 break;\r
5397 }\r
5398 }\r
5399 }\r
93e3992d 5400\r
84f9a9ec
LG
5401 //\r
5402 // Try to find driver handle by device path.\r
5403 //\r
5404 if (DriverHandle == NULL) {\r
5405 TempDevicePath = DevicePath;\r
5406 Status = gBS->LocateDevicePath (\r
5407 &gEfiDevicePathProtocolGuid,\r
5408 &TempDevicePath,\r
5409 &DriverHandle\r
5410 );\r
5411 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
5412 //\r
5413 // Routing data does not match any known driver.\r
5414 // Set Progress to the 'G' in "GUID" of the routing header.\r
5415 //\r
5416 FreePool (DevicePath);\r
5417 *Progress = StringPtr;\r
5418 FreePool (ConfigResp);\r
5419 return EFI_NOT_FOUND;\r
5420 }\r
93e3992d 5421 }\r
5422\r
84f9a9ec
LG
5423 FreePool (DevicePath);\r
5424\r
93e3992d 5425 //\r
cce6230f 5426 // Check whether this ConfigRequest is search from Efi varstore type storage.\r
93e3992d 5427 //\r
cce6230f
ED
5428 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
5429 if (EFI_ERROR (Status)) {\r
5430 return Status;\r
5431 }\r
93e3992d 5432\r
cce6230f
ED
5433 if (IsEfiVarstore) {\r
5434 //\r
5435 // Call the SetVariable function to route settings.\r
5436 // \r
5437 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
5438 FreePool (EfiVarStoreInfo);\r
5439 } else {\r
5440 //\r
5441 // Call corresponding ConfigAccess protocol to route settings\r
5442 //\r
5443 Status = gBS->HandleProtocol (\r
5444 DriverHandle,\r
5445 &gEfiHiiConfigAccessProtocolGuid,\r
5446 (VOID **) &ConfigAccess\r
5447 );\r
1f9f60ad
DB
5448 if (EFI_ERROR (Status)) {\r
5449 *Progress = StringPtr;\r
5450 FreePool (ConfigResp);\r
5451 return EFI_NOT_FOUND;\r
5452 }\r
93e3992d 5453\r
cce6230f
ED
5454 Status = ConfigAccess->RouteConfig (\r
5455 ConfigAccess,\r
5456 ConfigResp,\r
5457 &AccessProgress\r
5458 );\r
5459 }\r
93e3992d 5460 if (EFI_ERROR (Status)) {\r
523f48e7 5461 ASSERT (AccessProgress != NULL);\r
93e3992d 5462 //\r
5463 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
5464 // Map it to the progress on <MultiConfigResp> then return it.\r
5465 //\r
8d00a0f1 5466 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 5467\r
676df92c 5468 FreePool (ConfigResp);\r
93e3992d 5469 return Status;\r
5470 }\r
5471\r
676df92c 5472 FreePool (ConfigResp);\r
93e3992d 5473 ConfigResp = NULL;\r
5474\r
5475 //\r
5476 // Go to next <ConfigResp> (skip '&').\r
5477 //\r
5478 StringPtr += Length;\r
5479 if (*StringPtr == 0) {\r
5480 *Progress = StringPtr;\r
5481 break;\r
5482 }\r
5483\r
5484 StringPtr++;\r
5485\r
5486 }\r
5487\r
5488 return EFI_SUCCESS;\r
93e3992d 5489}\r
5490\r
5491\r
5492/**\r
5493 This helper function is to be called by drivers to map configuration data\r
5494 stored in byte array ("block") formats such as UEFI Variables into current\r
5495 configuration strings.\r
5496\r
5497 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5498 instance.\r
5499 @param ConfigRequest A null-terminated Unicode string in\r
5500 <ConfigRequest> format.\r
5501 @param Block Array of bytes defining the block's configuration.\r
5502 @param BlockSize Length in bytes of Block.\r
5503 @param Config Filled-in configuration string. String allocated\r
5504 by the function. Returned only if call is\r
84f9a9ec 5505 successful. It is <ConfigResp> string format.\r
93e3992d 5506 @param Progress A pointer to a string filled in with the offset of\r
5507 the most recent & before the first failing\r
5508 name/value pair (or the beginning of the string if\r
5509 the failure is in the first name / value pair) or\r
5510 the terminating NULL if all was successful.\r
5511\r
5512 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
5513 terminator at the end of the ConfigRequest\r
5514 string.\r
5515 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
5516 points to the first character of ConfigRequest.\r
5517 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
5518 Block parameter would result in this type of\r
5519 error. Progress points to the first character of\r
5520 ConfigRequest.\r
5521 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
5522 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
5523 Block is left updated and Progress points at\r
5524 the "&" preceding the first non-<BlockName>.\r
5525\r
5526**/\r
5527EFI_STATUS\r
5528EFIAPI\r
5529HiiBlockToConfig (\r
5530 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5531 IN CONST EFI_STRING ConfigRequest,\r
5532 IN CONST UINT8 *Block,\r
5533 IN CONST UINTN BlockSize,\r
5534 OUT EFI_STRING *Config,\r
5535 OUT EFI_STRING *Progress\r
5536 )\r
5537{\r
84f9a9ec 5538 HII_DATABASE_PRIVATE_DATA *Private;\r
93e3992d 5539 EFI_STRING StringPtr;\r
5540 UINTN Length;\r
5541 EFI_STATUS Status;\r
5542 EFI_STRING TmpPtr;\r
5543 UINT8 *TmpBuffer;\r
5544 UINTN Offset;\r
5545 UINTN Width;\r
5546 UINT8 *Value;\r
5547 EFI_STRING ValueStr;\r
5548 EFI_STRING ConfigElement;\r
63d55bb9
LG
5549 UINTN Index;\r
5550 UINT8 *TemBuffer;\r
5551 CHAR16 *TemString;\r
41ff10dc 5552 CHAR16 TemChar;\r
93e3992d 5553\r
4e1005ec
ED
5554 TmpBuffer = NULL;\r
5555\r
93e3992d 5556 if (This == NULL || Progress == NULL || Config == NULL) {\r
5557 return EFI_INVALID_PARAMETER;\r
5558 }\r
5559\r
5560 if (Block == NULL || ConfigRequest == NULL) {\r
5561 *Progress = ConfigRequest;\r
5562 return EFI_INVALID_PARAMETER;\r
5563 }\r
5564\r
84f9a9ec
LG
5565\r
5566 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5567 ASSERT (Private != NULL);\r
5568\r
93e3992d 5569 StringPtr = ConfigRequest;\r
5570 ValueStr = NULL;\r
5571 Value = NULL;\r
5572 ConfigElement = NULL;\r
5573\r
5574 //\r
5575 // Allocate a fix length of memory to store Results. Reallocate memory for\r
5576 // Results if this fix length is insufficient.\r
5577 //\r
5578 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
5579 if (*Config == NULL) {\r
5580 return EFI_OUT_OF_RESOURCES;\r
5581 }\r
5582\r
5583 //\r
5584 // Jump <ConfigHdr>\r
5585 //\r
5586 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
5587 *Progress = StringPtr;\r
5588 Status = EFI_INVALID_PARAMETER;\r
5589 goto Exit;\r
5590 }\r
5591 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
5592 StringPtr++;\r
5593 }\r
5594 if (*StringPtr == 0) {\r
76c24251 5595 *Progress = StringPtr - 1;\r
93e3992d 5596 Status = EFI_INVALID_PARAMETER;\r
5597 goto Exit;\r
5598 }\r
08e6463a 5599\r
5600 while (*StringPtr != L'&' && *StringPtr != 0) {\r
5601 StringPtr++;\r
5602 }\r
5603 if (*StringPtr == 0) {\r
41ff10dc 5604 *Progress = StringPtr;\r
41ff10dc
ED
5605\r
5606 AppendToMultiString(Config, ConfigRequest);\r
5607 HiiToLower (*Config);\r
5608\r
96179cb3 5609 return EFI_SUCCESS;\r
08e6463a 5610 }\r
5611 //\r
5612 // Skip '&'\r
5613 //\r
5614 StringPtr++;\r
93e3992d 5615\r
5616 //\r
5617 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
5618 //\r
41ff10dc
ED
5619 TemChar = *StringPtr;\r
5620 *StringPtr = '\0';\r
5621 AppendToMultiString(Config, ConfigRequest);\r
5622 *StringPtr = TemChar;\r
93e3992d 5623\r
5624 //\r
5625 // Parse each <RequestElement> if exists\r
5626 // Only <BlockName> format is supported by this help function.\r
5627 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
5628 //\r
5629 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
5630 //\r
5631 // Back up the header of one <BlockName>\r
5632 //\r
5633 TmpPtr = StringPtr;\r
5634\r
5635 StringPtr += StrLen (L"OFFSET=");\r
5636 //\r
5637 // Get Offset\r
5638 //\r
5639 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 5640 if (EFI_ERROR (Status)) {\r
46c3efbb 5641 *Progress = TmpPtr - 1;\r
93e3992d 5642 goto Exit;\r
5643 }\r
5644 Offset = 0;\r
5645 CopyMem (\r
5646 &Offset,\r
5647 TmpBuffer,\r
5648 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5649 );\r
676df92c 5650 FreePool (TmpBuffer);\r
93e3992d 5651\r
5652 StringPtr += Length;\r
5653 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 5654 *Progress = TmpPtr - 1;\r
93e3992d 5655 Status = EFI_INVALID_PARAMETER;\r
5656 goto Exit;\r
5657 }\r
5658 StringPtr += StrLen (L"&WIDTH=");\r
5659\r
5660 //\r
5661 // Get Width\r
5662 //\r
5663 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 5664 if (EFI_ERROR (Status)) {\r
46c3efbb 5665 *Progress = TmpPtr - 1;\r
93e3992d 5666 goto Exit;\r
5667 }\r
5668 Width = 0;\r
5669 CopyMem (\r
5670 &Width,\r
5671 TmpBuffer,\r
5672 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5673 );\r
676df92c 5674 FreePool (TmpBuffer);\r
93e3992d 5675\r
5676 StringPtr += Length;\r
5677 if (*StringPtr != 0 && *StringPtr != L'&') {\r
46c3efbb 5678 *Progress = TmpPtr - 1;\r
93e3992d 5679 Status = EFI_INVALID_PARAMETER;\r
5680 goto Exit;\r
5681 }\r
5682\r
5683 //\r
5684 // Calculate Value and convert it to hex string.\r
5685 //\r
5686 if (Offset + Width > BlockSize) {\r
5687 *Progress = StringPtr;\r
5688 Status = EFI_DEVICE_ERROR;\r
5689 goto Exit;\r
5690 }\r
5691\r
5692 Value = (UINT8 *) AllocateZeroPool (Width);\r
5693 if (Value == NULL) {\r
5694 *Progress = ConfigRequest;\r
5695 Status = EFI_OUT_OF_RESOURCES;\r
5696 goto Exit;\r
5697 }\r
5698\r
5699 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
5700\r
5701 Length = Width * 2 + 1;\r
5702 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
5703 if (ValueStr == NULL) {\r
5704 *Progress = ConfigRequest;\r
5705 Status = EFI_OUT_OF_RESOURCES;\r
5706 goto Exit;\r
5707 }\r
63d55bb9
LG
5708 \r
5709 TemString = ValueStr;\r
5710 TemBuffer = Value + Width - 1;\r
5711 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
9f4048f7
HW
5712 UnicodeValueToStringS (\r
5713 TemString,\r
5714 Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),\r
5715 PREFIX_ZERO | RADIX_HEX,\r
5716 *TemBuffer,\r
5717 2\r
5718 );\r
5719 TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));\r
63d55bb9 5720 }\r
813acf3a 5721\r
676df92c 5722 FreePool (Value);\r
93e3992d 5723 Value = NULL;\r
5724\r
5725 //\r
5726 // Build a ConfigElement\r
5727 //\r
5728 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
5729 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
5730 if (ConfigElement == NULL) {\r
5731 Status = EFI_OUT_OF_RESOURCES;\r
5732 goto Exit;\r
5733 }\r
5734 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
5735 if (*StringPtr == 0) {\r
5736 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
5737 }\r
5738 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
5ad66ec6
DB
5739 StrCatS (ConfigElement, Length, L"VALUE=");\r
5740 StrCatS (ConfigElement, Length, ValueStr);\r
93e3992d 5741\r
5742 AppendToMultiString (Config, ConfigElement);\r
5743\r
676df92c 5744 FreePool (ConfigElement);\r
5745 FreePool (ValueStr);\r
93e3992d 5746 ConfigElement = NULL;\r
5747 ValueStr = NULL;\r
5748\r
5749 //\r
5750 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
5751 //\r
5752 if (*StringPtr == 0) {\r
5753 break;\r
5754 }\r
5755 AppendToMultiString (Config, L"&");\r
5756 StringPtr++;\r
5757\r
5758 }\r
5759\r
5760 if (*StringPtr != 0) {\r
5761 *Progress = StringPtr - 1;\r
5762 Status = EFI_INVALID_PARAMETER;\r
5763 goto Exit;\r
5764 }\r
84f9a9ec
LG
5765 \r
5766 HiiToLower (*Config);\r
93e3992d 5767 *Progress = StringPtr;\r
5768 return EFI_SUCCESS;\r
5769\r
5770Exit:\r
76c24251 5771 if (*Config != NULL) {\r
1f1cb2f2
LG
5772 FreePool (*Config);\r
5773 *Config = NULL;\r
76c24251 5774 }\r
676df92c 5775 if (ValueStr != NULL) {\r
5776 FreePool (ValueStr);\r
5777 }\r
5778 if (Value != NULL) {\r
5779 FreePool (Value);\r
5780 }\r
69367b5b 5781 if (ConfigElement != NULL) {\r
676df92c 5782 FreePool (ConfigElement);\r
5783 }\r
93e3992d 5784\r
5785 return Status;\r
5786\r
5787}\r
5788\r
5789\r
5790/**\r
5791 This helper function is to be called by drivers to map configuration strings\r
5792 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
5793\r
5794 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
5795 instance.\r
5796 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
771ececd 5797 format.\r
93e3992d 5798 @param Block A possibly null array of bytes representing the\r
5799 current block. Only bytes referenced in the\r
5800 ConfigResp string in the block are modified. If\r
5801 this parameter is null or if the *BlockSize\r
5802 parameter is (on input) shorter than required by\r
5803 the Configuration string, only the BlockSize\r
5804 parameter is updated and an appropriate status\r
5805 (see below) is returned.\r
5806 @param BlockSize The length of the Block in units of UINT8. On\r
5807 input, this is the size of the Block. On output,\r
c0a3c3da
ED
5808 if successful, contains the largest index of the\r
5809 modified byte in the Block, or the required buffer\r
5810 size if the Block is not large enough.\r
93e3992d 5811 @param Progress On return, points to an element of the ConfigResp\r
5812 string filled in with the offset of the most\r
5813 recent '&' before the first failing name / value\r
5814 pair (or the beginning of the string if the\r
5815 failure is in the first name / value pair) or the\r
5816 terminating NULL if all was successful.\r
5817\r
5818 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
5819 terminator at the end of the ConfigResp string.\r
5820 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
5821 points to the first character of ConfigResp.\r
5822 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
5823 Block parameter would result in this type of\r
5824 error. Progress points to the first character of\r
5825 ConfigResp.\r
5826 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
5827 value pair. Block is left updated and\r
5828 Progress points at the '&' preceding the first\r
5829 non-<BlockName>.\r
c0a3c3da
ED
5830 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined. \r
5831 BlockSize is updated with the required buffer size.\r
09b79417
LG
5832 @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
5833 Progress points to the "G" in "GUID" of the errant\r
5834 routing data.\r
93e3992d 5835\r
5836**/\r
5837EFI_STATUS\r
5838EFIAPI\r
5839HiiConfigToBlock (\r
5840 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
5841 IN CONST EFI_STRING ConfigResp,\r
5842 IN OUT UINT8 *Block,\r
5843 IN OUT UINTN *BlockSize,\r
5844 OUT EFI_STRING *Progress\r
5845 )\r
5846{\r
5847 HII_DATABASE_PRIVATE_DATA *Private;\r
5848 EFI_STRING StringPtr;\r
46c3efbb 5849 EFI_STRING TmpPtr;\r
93e3992d 5850 UINTN Length;\r
5851 EFI_STATUS Status;\r
5852 UINT8 *TmpBuffer;\r
5853 UINTN Offset;\r
5854 UINTN Width;\r
5855 UINT8 *Value;\r
5856 UINTN BufferSize;\r
09b79417 5857 UINTN MaxBlockSize;\r
93e3992d 5858\r
4e1005ec
ED
5859 TmpBuffer = NULL;\r
5860\r
93e3992d 5861 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
5862 return EFI_INVALID_PARAMETER;\r
5863 }\r
5864\r
09b79417
LG
5865 *Progress = ConfigResp;\r
5866 if (ConfigResp == NULL) {\r
93e3992d 5867 return EFI_INVALID_PARAMETER;\r
5868 }\r
5869\r
5870 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
5871 ASSERT (Private != NULL);\r
5872\r
5873 StringPtr = ConfigResp;\r
5874 BufferSize = *BlockSize;\r
5875 Value = NULL;\r
09b79417 5876 MaxBlockSize = 0;\r
93e3992d 5877\r
5878 //\r
5879 // Jump <ConfigHdr>\r
5880 //\r
5881 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
5882 *Progress = StringPtr;\r
5883 Status = EFI_INVALID_PARAMETER;\r
5884 goto Exit;\r
5885 }\r
5886 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
5887 StringPtr++;\r
5888 }\r
5889 if (*StringPtr == 0) {\r
5890 *Progress = StringPtr;\r
5891 Status = EFI_INVALID_PARAMETER;\r
5892 goto Exit;\r
5893 }\r
08e6463a 5894\r
5895 while (*StringPtr != L'&' && *StringPtr != 0) {\r
5896 StringPtr++;\r
5897 }\r
5898 if (*StringPtr == 0) {\r
5899 *Progress = StringPtr;\r
5900 Status = EFI_INVALID_PARAMETER;\r
5901 goto Exit;\r
5902 }\r
93e3992d 5903\r
5904 //\r
5905 // Parse each <ConfigElement> if exists\r
edae8d2d 5906 // Only '&'<BlockConfig> format is supported by this help function.\r
93e3992d 5907 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
5908 //\r
edae8d2d 5909 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
46c3efbb 5910 TmpPtr = StringPtr;\r
edae8d2d 5911 StringPtr += StrLen (L"&OFFSET=");\r
93e3992d 5912 //\r
5913 // Get Offset\r
5914 //\r
5915 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 5916 if (EFI_ERROR (Status)) {\r
46c3efbb 5917 *Progress = TmpPtr;\r
93e3992d 5918 goto Exit;\r
5919 }\r
5920 Offset = 0;\r
5921 CopyMem (\r
5922 &Offset,\r
5923 TmpBuffer,\r
5924 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5925 );\r
676df92c 5926 FreePool (TmpBuffer);\r
93e3992d 5927\r
5928 StringPtr += Length;\r
5929 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
46c3efbb 5930 *Progress = TmpPtr;\r
93e3992d 5931 Status = EFI_INVALID_PARAMETER;\r
5932 goto Exit;\r
5933 }\r
5934 StringPtr += StrLen (L"&WIDTH=");\r
5935\r
5936 //\r
5937 // Get Width\r
5938 //\r
5939 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
3a530010 5940 if (EFI_ERROR (Status)) {\r
46c3efbb 5941 *Progress = TmpPtr;\r
93e3992d 5942 goto Exit;\r
5943 }\r
5944 Width = 0;\r
5945 CopyMem (\r
5946 &Width,\r
5947 TmpBuffer,\r
5948 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
5949 );\r
676df92c 5950 FreePool (TmpBuffer);\r
93e3992d 5951\r
5952 StringPtr += Length;\r
5953 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
46c3efbb 5954 *Progress = TmpPtr;\r
93e3992d 5955 Status = EFI_INVALID_PARAMETER;\r
5956 goto Exit;\r
5957 }\r
5958 StringPtr += StrLen (L"&VALUE=");\r
5959\r
5960 //\r
5961 // Get Value\r
5962 //\r
5963 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 5964 if (EFI_ERROR (Status)) {\r
46c3efbb 5965 *Progress = TmpPtr;\r
93e3992d 5966 goto Exit;\r
5967 }\r
5968\r
5969 StringPtr += Length;\r
5970 if (*StringPtr != 0 && *StringPtr != L'&') {\r
46c3efbb 5971 *Progress = TmpPtr;\r
93e3992d 5972 Status = EFI_INVALID_PARAMETER;\r
5973 goto Exit;\r
5974 }\r
5975\r
5976 //\r
5977 // Update the Block with configuration info\r
5978 //\r
09b79417
LG
5979 if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
5980 CopyMem (Block + Offset, Value, Width);\r
5981 }\r
5982 if (Offset + Width > MaxBlockSize) {\r
5983 MaxBlockSize = Offset + Width;\r
93e3992d 5984 }\r
93e3992d 5985\r
676df92c 5986 FreePool (Value);\r
93e3992d 5987 Value = NULL;\r
5988\r
5989 //\r
edae8d2d 5990 // If '\0', parsing is finished.\r
93e3992d 5991 //\r
5992 if (*StringPtr == 0) {\r
5993 break;\r
5994 }\r
93e3992d 5995 }\r
84f9a9ec
LG
5996 \r
5997 //\r
edae8d2d 5998 // The input string is not ConfigResp format, return error.\r
84f9a9ec 5999 //\r
edae8d2d
ED
6000 if (*StringPtr != 0) {\r
6001 *Progress = StringPtr;\r
93e3992d 6002 Status = EFI_INVALID_PARAMETER;\r
6003 goto Exit;\r
6004 }\r
6005\r
6e3f5b2a 6006 *Progress = StringPtr + StrLen (StringPtr);\r
09b79417
LG
6007 *BlockSize = MaxBlockSize - 1;\r
6008\r
6009 if (MaxBlockSize > BufferSize) {\r
6010 *BlockSize = MaxBlockSize;\r
9ac0640d 6011 if (Block != NULL) {\r
c0a3c3da 6012 return EFI_BUFFER_TOO_SMALL;\r
09b79417
LG
6013 }\r
6014 }\r
6015\r
9ac0640d
LG
6016 if (Block == NULL) {\r
6017 *Progress = ConfigResp;\r
6018 return EFI_INVALID_PARAMETER;\r
6019 }\r
6020\r
93e3992d 6021 return EFI_SUCCESS;\r
6022\r
6023Exit:\r
6024\r
676df92c 6025 if (Value != NULL) {\r
6026 FreePool (Value);\r
6027 }\r
93e3992d 6028 return Status;\r
6029}\r
6030\r
6031\r
6032/**\r
6033 This helper function is to be called by drivers to extract portions of\r
6034 a larger configuration string.\r
6035\r
6036 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
6037 instance.\r
6038 @param Configuration A null-terminated Unicode string in\r
771ececd 6039 <MultiConfigAltResp> format.\r
93e3992d 6040 @param Guid A pointer to the GUID value to search for in the\r
6041 routing portion of the ConfigResp string when\r
6042 retrieving the requested data. If Guid is NULL,\r
6043 then all GUID values will be searched for.\r
6044 @param Name A pointer to the NAME value to search for in the\r
6045 routing portion of the ConfigResp string when\r
6046 retrieving the requested data. If Name is NULL,\r
6047 then all Name values will be searched for.\r
6048 @param DevicePath A pointer to the PATH value to search for in the\r
6049 routing portion of the ConfigResp string when\r
6050 retrieving the requested data. If DevicePath is\r
6051 NULL, then all DevicePath values will be searched\r
6052 for.\r
6053 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
6054 routing portion of the ConfigResp string when\r
6055 retrieving the requested data. If this parameter\r
6056 is NULL, then the current setting will be\r
6057 retrieved.\r
6058 @param AltCfgResp A pointer to a buffer which will be allocated by\r
6059 the function which contains the retrieved string\r
6060 as requested. This buffer is only allocated if\r
84f9a9ec 6061 the call was successful. It is <ConfigResp> format.\r
93e3992d 6062\r
6063 @retval EFI_SUCCESS The request succeeded. The requested data was\r
6064 extracted and placed in the newly allocated\r
6065 AltCfgResp buffer.\r
6066 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
6067 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
6068 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
6069 found.\r
6070\r
6071**/\r
6072EFI_STATUS\r
6073EFIAPI\r
6074HiiGetAltCfg (\r
6075 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
6076 IN CONST EFI_STRING Configuration,\r
6077 IN CONST EFI_GUID *Guid,\r
6078 IN CONST EFI_STRING Name,\r
6079 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
6080 IN CONST UINT16 *AltCfgId,\r
6081 OUT EFI_STRING *AltCfgResp\r
6082 )\r
6083{\r
93e3992d 6084 EFI_STATUS Status;\r
6085 EFI_STRING StringPtr;\r
e90b081a 6086 EFI_STRING HdrStart;\r
6087 EFI_STRING HdrEnd;\r
93e3992d 6088 EFI_STRING TmpPtr;\r
6089 UINTN Length;\r
e90b081a 6090 EFI_STRING GuidStr;\r
6091 EFI_STRING NameStr;\r
6092 EFI_STRING PathStr;\r
6093 EFI_STRING AltIdStr;\r
6094 EFI_STRING Result;\r
6095 BOOLEAN GuidFlag;\r
6096 BOOLEAN NameFlag;\r
6097 BOOLEAN PathFlag;\r
6098\r
6099 HdrStart = NULL;\r
6100 HdrEnd = NULL;\r
6101 GuidStr = NULL;\r
6102 NameStr = NULL;\r
6103 PathStr = NULL;\r
6104 AltIdStr = NULL;\r
6105 Result = NULL;\r
6106 GuidFlag = FALSE;\r
6107 NameFlag = FALSE;\r
6108 PathFlag = FALSE;\r
93e3992d 6109\r
6110 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
6111 return EFI_INVALID_PARAMETER;\r
6112 }\r
6113\r
6114 StringPtr = Configuration;\r
6115 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
6116 return EFI_INVALID_PARAMETER;\r
6117 }\r
6118\r
6119 //\r
6120 // Generate the sub string for later matching.\r
6121 //\r
813acf3a 6122 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 6123 GenerateSubStr (\r
6124 L"PATH=",\r
6125 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 6126 (VOID *) DevicePath,\r
6127 1,\r
93e3992d 6128 &PathStr\r
6129 );\r
6130 if (AltCfgId != NULL) {\r
813acf3a 6131 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 6132 }\r
6133 if (Name != NULL) {\r
813acf3a 6134 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 6135 } else {\r
813acf3a 6136 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 6137 }\r
6138\r
6139 while (*StringPtr != 0) {\r
6140 //\r
6141 // Try to match the GUID\r
6142 //\r
6143 if (!GuidFlag) {\r
6144 TmpPtr = StrStr (StringPtr, GuidStr);\r
6145 if (TmpPtr == NULL) {\r
6146 Status = EFI_NOT_FOUND;\r
6147 goto Exit;\r
6148 }\r
6149 HdrStart = TmpPtr;\r
6150\r
6151 //\r
6152 // Jump to <NameHdr>\r
6153 //\r
6154 if (Guid != NULL) {\r
6155 StringPtr = TmpPtr + StrLen (GuidStr);\r
6156 } else {\r
6157 StringPtr = StrStr (TmpPtr, L"NAME=");\r
6158 if (StringPtr == NULL) {\r
6159 Status = EFI_NOT_FOUND;\r
6160 goto Exit;\r
6161 }\r
6162 }\r
6163 GuidFlag = TRUE;\r
6164 }\r
6165\r
6166 //\r
6167 // Try to match the NAME\r
6168 //\r
6169 if (GuidFlag && !NameFlag) {\r
6170 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
6171 GuidFlag = FALSE;\r
6172 } else {\r
6173 //\r
6174 // Jump to <PathHdr>\r
6175 //\r
6176 if (Name != NULL) {\r
6177 StringPtr += StrLen (NameStr);\r
6178 } else {\r
6179 StringPtr = StrStr (StringPtr, L"PATH=");\r
6180 if (StringPtr == NULL) {\r
6181 Status = EFI_NOT_FOUND;\r
6182 goto Exit;\r
6183 }\r
6184 }\r
6185 NameFlag = TRUE;\r
6186 }\r
6187 }\r
6188\r
6189 //\r
6190 // Try to match the DevicePath\r
6191 //\r
6192 if (GuidFlag && NameFlag && !PathFlag) {\r
6193 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
6194 GuidFlag = FALSE;\r
6195 NameFlag = FALSE;\r
6196 } else {\r
6197 //\r
6198 // Jump to '&' before <DescHdr> or <ConfigBody>\r
6199 //\r
6200 if (DevicePath != NULL) {\r
6201 StringPtr += StrLen (PathStr);\r
6202 } else {\r
6203 StringPtr = StrStr (StringPtr, L"&");\r
6204 if (StringPtr == NULL) {\r
6205 Status = EFI_NOT_FOUND;\r
6206 goto Exit;\r
6207 }\r
84f9a9ec 6208 StringPtr ++;\r
93e3992d 6209 }\r
6210 PathFlag = TRUE;\r
84f9a9ec 6211 HdrEnd = StringPtr;\r
93e3992d 6212 }\r
6213 }\r
6214\r
6215 //\r
6216 // Try to match the AltCfgId\r
6217 //\r
6218 if (GuidFlag && NameFlag && PathFlag) {\r
6219 if (AltCfgId == NULL) {\r
6220 //\r
6221 // Return Current Setting when AltCfgId is NULL.\r
6222 //\r
6223 Status = OutputConfigBody (StringPtr, &Result);\r
6224 goto Exit;\r
6225 }\r
6226 //\r
6227 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
6228 //\r
6229 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
6230 GuidFlag = FALSE;\r
6231 NameFlag = FALSE;\r
6232 PathFlag = FALSE;\r
6233 } else {\r
84f9a9ec
LG
6234 //\r
6235 // Skip AltIdStr and &\r
6236 //\r
6237 StringPtr = StringPtr + StrLen (AltIdStr);\r
6238 Status = OutputConfigBody (StringPtr, &Result);\r
93e3992d 6239 goto Exit;\r
6240 }\r
6241 }\r
6242 }\r
6243\r
6244 Status = EFI_NOT_FOUND;\r
6245\r
6246Exit:\r
76c24251 6247 *AltCfgResp = NULL;\r
bc166db3 6248 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 6249 //\r
6250 // Copy the <ConfigHdr> and <ConfigBody>\r
6251 //\r
84f9a9ec 6252 Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
93e3992d 6253 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
6254 if (*AltCfgResp == NULL) {\r
6255 Status = EFI_OUT_OF_RESOURCES;\r
6256 } else {\r
5ad66ec6
DB
6257 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);\r
6258 StrCatS (*AltCfgResp, Length, Result);\r
93e3992d 6259 Status = EFI_SUCCESS;\r
6260 }\r
6261 }\r
6262\r
676df92c 6263 if (GuidStr != NULL) {\r
6264 FreePool (GuidStr);\r
6265 }\r
6266 if (NameStr != NULL) {\r
6267 FreePool (NameStr);\r
6268 }\r
6269 if (PathStr != NULL) {\r
6270 FreePool (PathStr);\r
6271 }\r
6272 if (AltIdStr != NULL) {\r
6273 FreePool (AltIdStr);\r
6274 }\r
6275 if (Result != NULL) {\r
6276 FreePool (Result);\r
6277 }\r
93e3992d 6278\r
6279 return Status;\r
6280\r
93e3992d 6281}\r
6282\r
36fe40c2 6283\r