]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
correct the minor format.
[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
36fe40c2 4Copyright (c) 2007 - 2008, Intel Corporation\r
93e3992d 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
93e3992d 13**/\r
14\r
15\r
16#include "HiiDatabase.h"\r
17\r
93e3992d 18/**\r
19 Calculate the number of Unicode characters of the incoming Configuration string,\r
20 not including NULL terminator.\r
21\r
e90b081a 22 This is a internal function.\r
23\r
93e3992d 24 @param String String in <MultiConfigRequest> or\r
25 <MultiConfigResp> format.\r
26\r
27 @return The number of Unicode characters.\r
28\r
29**/\r
93e3992d 30UINTN\r
31CalculateConfigStringLen (\r
32 IN EFI_STRING String\r
33 )\r
34{\r
35 UINTN Length;\r
36\r
37 //\r
38 // "GUID=" should be the first element of incoming string.\r
39 //\r
40 ASSERT (String != NULL);\r
41 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
42\r
43 Length = StrLen (L"GUID=");\r
44 String += Length;\r
45\r
46 //\r
47 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
48 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
49 //\r
50 while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {\r
51 Length++;\r
52 String++;\r
53 }\r
54\r
55 return Length;\r
56}\r
57\r
58\r
59/**\r
60 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
61 from <PathHdr> of <ConfigHdr>.\r
62\r
e90b081a 63 This is a internal function.\r
64\r
93e3992d 65 @param String UEFI configuration string\r
66 @param DevicePath binary of a UEFI device path.\r
67\r
68 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
69 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
70 @retval EFI_SUCCESS The device path is retrieved and translated to\r
71 binary format.\r
72\r
73**/\r
93e3992d 74EFI_STATUS\r
75GetDevicePath (\r
76 IN EFI_STRING String,\r
77 OUT UINT8 **DevicePath\r
78 )\r
79{\r
80 UINTN Length;\r
81 EFI_STRING PathHdr;\r
82 EFI_STRING DevicePathString;\r
63d55bb9
LG
83 UINT8 *DevicePathBuffer;\r
84 CHAR16 TemStr[2];\r
85 UINTN Index;\r
86 UINT8 DigitUint8;\r
93e3992d 87\r
88 if (String == NULL || DevicePath == NULL) {\r
89 return EFI_INVALID_PARAMETER;\r
90 }\r
91\r
92 //\r
93 // Find the 'PATH=' of <PathHdr> and skip it.\r
94 //\r
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
96 if (*String == 0) {\r
97 return EFI_INVALID_PARAMETER;\r
98 }\r
99\r
100 String += StrLen (L"PATH=");\r
101 PathHdr = String;\r
102\r
103 //\r
104 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
105 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
106 // of UEFI device path.\r
107 //\r
108 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
109 DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
110 if (DevicePathString == NULL) {\r
111 return EFI_OUT_OF_RESOURCES;\r
112 }\r
113 StrnCpy (DevicePathString, PathHdr, Length);\r
114 *(DevicePathString + Length) = 0;\r
115\r
116 //\r
117 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
118 // as the device path resides in RAM memory.\r
119 // Translate the data into binary.\r
93e3992d 120 //\r
63d55bb9
LG
121 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
122 if (DevicePathBuffer == NULL) {\r
676df92c 123 FreePool (DevicePathString);\r
93e3992d 124 return EFI_OUT_OF_RESOURCES;\r
125 }\r
126\r
63d55bb9
LG
127 ZeroMem (TemStr, sizeof (TemStr));\r
128 for (Index = 0; DevicePathString[Index] != L'\0'; Index ++) {\r
129 TemStr[0] = DevicePathString[Index];\r
130 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
131 if ((Index & 1) == 0) {\r
132 DevicePathBuffer [Index/2] = DigitUint8;\r
133 } else {\r
134 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
135 }\r
136 }\r
93e3992d 137\r
676df92c 138 FreePool (DevicePathString);\r
63d55bb9
LG
139 \r
140 *DevicePath = DevicePathBuffer;\r
93e3992d 141\r
142 return EFI_SUCCESS;\r
143\r
144}\r
145\r
63d55bb9
LG
146/**\r
147 Converts the unicode character of the string from uppercase to lowercase.\r
148 This is a internal function.\r
149\r
150 @param Str String to be converted\r
151\r
152**/\r
153VOID\r
154EFIAPI\r
155HiiToLower (\r
156 IN OUT CHAR16 *Str\r
157 )\r
158{\r
159 CHAR16 *Ptr;\r
160 \r
161 for (Ptr = Str; *Ptr != L'\0'; Ptr++) {\r
162 if (*Ptr >= L'A' && *Ptr <= L'Z') {\r
163 *Ptr = (CHAR16) (*Ptr - L'A' + L'a');\r
164 }\r
165 }\r
166}\r
93e3992d 167\r
93e3992d 168/**\r
169 Generate a sub string then output it.\r
170\r
e90b081a 171 This is a internal function.\r
172\r
93e3992d 173 @param String A constant string which is the prefix of the to be\r
174 generated string, e.g. GUID=\r
175 @param BufferLen The length of the Buffer in bytes.\r
813acf3a 176 @param Buffer Points to a buffer which will be converted to be the \r
177 content of the generated string.\r
178 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
179 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
180 if 3, the buffer contains other data.\r
93e3992d 181 @param SubStr Points to the output string. It's caller's\r
182 responsibility to free this buffer.\r
183\r
184\r
185**/\r
93e3992d 186VOID\r
187GenerateSubStr (\r
188 IN CONST EFI_STRING String,\r
189 IN UINTN BufferLen,\r
813acf3a 190 IN VOID *Buffer,\r
191 IN UINT8 Flag,\r
93e3992d 192 OUT EFI_STRING *SubStr\r
193 )\r
194{\r
195 UINTN Length;\r
196 EFI_STRING Str;\r
813acf3a 197 EFI_STRING StringHeader;\r
63d55bb9
LG
198 CHAR16 *TemString;\r
199 CHAR16 *TemName;\r
200 UINT8 *TemBuffer;\r
201 UINTN Index;\r
93e3992d 202\r
203 ASSERT (String != NULL && SubStr != NULL);\r
204\r
205 if (Buffer == NULL) {\r
206 *SubStr = AllocateCopyPool (StrSize (String), String);\r
207 ASSERT (*SubStr != NULL);\r
208 return ;\r
209 }\r
210\r
813acf3a 211 Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
63d55bb9 212 Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
93e3992d 213 ASSERT (Str != NULL);\r
214\r
215 StrCpy (Str, String);\r
216 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
217\r
813acf3a 218 StringHeader = Str + StrLen (String);\r
63d55bb9 219 TemString = (CHAR16 *) StringHeader;\r
813acf3a 220\r
221 switch (Flag) {\r
222 case 1:\r
63d55bb9
LG
223 //\r
224 // Convert Buffer to Hex String in reverse order\r
225 //\r
226 TemBuffer = ((UINT8 *) Buffer);\r
227 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {\r
228 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
229 }\r
813acf3a 230 break;\r
231 case 2:\r
63d55bb9
LG
232 //\r
233 // Check buffer is enough\r
234 //\r
235 TemName = (CHAR16 *) Buffer;\r
236 ASSERT (Length < ((StrLen (TemName) * 4 + 1) * sizeof (CHAR16)));\r
237 //\r
238 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
239 //\r
240 for (; *TemName != L'\0'; TemName++) {\r
241 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
242 }\r
813acf3a 243 break;\r
244 case 3:\r
813acf3a 245 //\r
63d55bb9 246 // Convert Buffer to Hex String\r
813acf3a 247 //\r
63d55bb9
LG
248 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;\r
249 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {\r
250 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
251 }\r
813acf3a 252 break;\r
253 default:\r
254 break;\r
255 }\r
93e3992d 256\r
63d55bb9
LG
257 //\r
258 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
259 //\r
260 HiiToLower (StringHeader);\r
93e3992d 261 StrCat (Str, L"&");\r
262\r
263 *SubStr = Str;\r
264}\r
265\r
266\r
267/**\r
268 Retrieve the <ConfigBody> from String then output it.\r
269\r
e90b081a 270 This is a internal function.\r
271\r
93e3992d 272 @param String A sub string of a configuration string in\r
273 <MultiConfigAltResp> format.\r
274 @param ConfigBody Points to the output string. It's caller's\r
275 responsibility to free this buffer.\r
276\r
277 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
278 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
279 @retval EFI_SUCCESS All existing storage is exported.\r
280\r
281**/\r
93e3992d 282EFI_STATUS\r
283OutputConfigBody (\r
284 IN EFI_STRING String,\r
285 OUT EFI_STRING *ConfigBody\r
286 )\r
287{\r
288 EFI_STRING TmpPtr;\r
289 EFI_STRING Result;\r
290 UINTN Length;\r
291\r
292 if (String == NULL || ConfigBody == NULL) {\r
293 return EFI_INVALID_PARAMETER;\r
294 }\r
295\r
296 TmpPtr = StrStr (String, L"GUID=");\r
297 if (TmpPtr == NULL) {\r
298 //\r
299 // It is the last <ConfigResp> of the incoming configuration string.\r
300 //\r
301 Result = AllocateCopyPool (StrSize (String), String);\r
302 if (Result == NULL) {\r
303 return EFI_OUT_OF_RESOURCES;\r
304 } else {\r
305 *ConfigBody = Result;\r
306 return EFI_SUCCESS;\r
307 }\r
308 }\r
309\r
310 Length = TmpPtr - String;\r
311 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
312 if (Result == NULL) {\r
313 return EFI_OUT_OF_RESOURCES;\r
314 }\r
315\r
316 *(Result + Length - 1) = 0;\r
317 *ConfigBody = Result;\r
318 return EFI_SUCCESS;\r
319\r
320}\r
321\r
93e3992d 322/**\r
323 Append a string to a multi-string format.\r
324\r
e90b081a 325 This is a internal function.\r
326\r
93e3992d 327 @param MultiString String in <MultiConfigRequest>,\r
328 <MultiConfigAltResp>, or <MultiConfigResp>. On\r
329 input, the buffer length of this string is\r
330 MAX_STRING_LENGTH. On output, the buffer length\r
331 might be updated.\r
332 @param AppendString NULL-terminated Unicode string.\r
333\r
334 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
335 @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
336\r
337**/\r
93e3992d 338EFI_STATUS\r
339AppendToMultiString (\r
340 IN OUT EFI_STRING *MultiString,\r
341 IN EFI_STRING AppendString\r
342 )\r
343{\r
344 UINTN AppendStringSize;\r
345 UINTN MultiStringSize;\r
346\r
347 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350\r
351 AppendStringSize = StrSize (AppendString);\r
352 MultiStringSize = StrSize (*MultiString);\r
353\r
354 //\r
355 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
356 //\r
357 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
358 MultiStringSize > MAX_STRING_LENGTH) {\r
359 *MultiString = (EFI_STRING) ReallocatePool (\r
93e3992d 360 MultiStringSize,\r
c4648495 361 MultiStringSize + AppendStringSize,\r
362 (VOID *) (*MultiString)\r
93e3992d 363 );\r
c59634ea 364 ASSERT (*MultiString != NULL);\r
93e3992d 365 }\r
93e3992d 366 //\r
367 // Append the incoming string\r
368 //\r
369 StrCat (*MultiString, AppendString);\r
370\r
371 return EFI_SUCCESS;\r
372}\r
373\r
374\r
375/**\r
376 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
377 or WIDTH or VALUE.\r
378 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
379\r
e90b081a 380 This is a internal function.\r
381\r
93e3992d 382 @param StringPtr String in <BlockConfig> format and points to the\r
383 first character of <Number>.\r
384 @param Number The output value. Caller takes the responsibility\r
385 to free memory.\r
386 @param Len Length of the <Number>, in characters.\r
387\r
388 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
389 structures.\r
390 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
391 successfully.\r
392\r
393**/\r
93e3992d 394EFI_STATUS\r
395GetValueOfNumber (\r
396 IN EFI_STRING StringPtr,\r
397 OUT UINT8 **Number,\r
398 OUT UINTN *Len\r
399 )\r
400{\r
401 EFI_STRING TmpPtr;\r
402 UINTN Length;\r
403 EFI_STRING Str;\r
404 UINT8 *Buf;\r
405 EFI_STATUS Status;\r
63d55bb9
LG
406 UINT8 DigitUint8;\r
407 UINTN Index;\r
408 CHAR16 TemStr[2];\r
93e3992d 409\r
410 ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
63d55bb9 411 ASSERT (*StringPtr != L'\0');\r
93e3992d 412\r
413 Buf = NULL;\r
414\r
415 TmpPtr = StringPtr;\r
63d55bb9 416 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
93e3992d 417 StringPtr++;\r
418 }\r
419 *Len = StringPtr - TmpPtr;\r
420 Length = *Len + 1;\r
421\r
422 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));\r
423 if (Str == NULL) {\r
424 Status = EFI_OUT_OF_RESOURCES;\r
425 goto Exit;\r
426 }\r
427 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
63d55bb9 428 *(Str + *Len) = L'\0';\r
93e3992d 429\r
430 Length = (Length + 1) / 2;\r
431 Buf = (UINT8 *) AllocateZeroPool (Length);\r
432 if (Buf == NULL) {\r
433 Status = EFI_OUT_OF_RESOURCES;\r
434 goto Exit;\r
435 }\r
63d55bb9
LG
436 \r
437 Length = *Len;\r
438 ZeroMem (TemStr, sizeof (TemStr));\r
439 for (Index = 0; Index < Length; Index ++) {\r
440 TemStr[0] = Str[Length - Index - 1];\r
441 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
442 if ((Index & 1) == 0) {\r
443 Buf [Index/2] = DigitUint8;\r
444 } else {\r
634303c9 445 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
63d55bb9 446 }\r
93e3992d 447 }\r
448\r
449 *Number = Buf;\r
450 Status = EFI_SUCCESS;\r
451\r
452Exit:\r
676df92c 453 if (Str != NULL) {\r
454 FreePool (Str);\r
455 }\r
63d55bb9 456\r
93e3992d 457 return Status;\r
458}\r
459\r
460\r
461/**\r
462 This function allows a caller to extract the current configuration\r
463 for one or more named elements from one or more drivers.\r
464\r
465 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
466 instance.\r
467 @param Request A null-terminated Unicode string in\r
468 <MultiConfigRequest> format.\r
469 @param Progress On return, points to a character in the Request\r
470 string. Points to the string's null terminator if\r
471 request was successful. Points to the most recent\r
472 & before the first failing name / value pair (or\r
473 the beginning of the string if the failure is in\r
474 the first name / value pair) if the request was\r
475 not successful.\r
476 @param Results Null-terminated Unicode string in\r
477 <MultiConfigAltResp> format which has all values\r
478 filled in for the names in the Request string.\r
479 String to be allocated by the called function.\r
480\r
481 @retval EFI_SUCCESS The Results string is filled with the values\r
482 corresponding to all requested names.\r
483 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
484 results that must be stored awaiting possible\r
485 future protocols.\r
486 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
487 Progress set to the "G" in "GUID" of the routing\r
488 header that doesn't match. Note: There is no\r
489 requirement that all routing data be validated\r
490 before any configuration extraction.\r
491 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
492 parameter would result in this type of error. The\r
493 Progress parameter is set to NULL.\r
494 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
495 before the error or the beginning of the string.\r
496 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
497 name in question.\r
498\r
499**/\r
500EFI_STATUS\r
501EFIAPI\r
502HiiConfigRoutingExtractConfig (\r
503 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
504 IN CONST EFI_STRING Request,\r
505 OUT EFI_STRING *Progress,\r
506 OUT EFI_STRING *Results\r
507 )\r
508{\r
93e3992d 509 HII_DATABASE_PRIVATE_DATA *Private;\r
510 EFI_STRING StringPtr;\r
511 EFI_STRING ConfigRequest;\r
512 UINTN Length;\r
513 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
514 EFI_STATUS Status;\r
515 LIST_ENTRY *Link;\r
516 HII_DATABASE_RECORD *Database;\r
08e6463a 517 UINT8 *DevicePathPkg;\r
93e3992d 518 UINT8 *CurrentDevicePath;\r
519 EFI_HANDLE DriverHandle;\r
520 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
521 EFI_STRING AccessProgress;\r
522 EFI_STRING AccessResults;\r
8d00a0f1 523 BOOLEAN FirstElement;\r
93e3992d 524\r
525 if (This == NULL || Progress == NULL || Results == NULL) {\r
526 return EFI_INVALID_PARAMETER;\r
527 }\r
528\r
529 if (Request == NULL) {\r
530 *Progress = NULL;\r
531 return EFI_INVALID_PARAMETER;\r
532 }\r
533\r
534 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
535 StringPtr = Request;\r
536 *Progress = StringPtr;\r
537\r
538 //\r
539 // The first element of <MultiConfigRequest> should be\r
540 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
541 //\r
542 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
543 return EFI_INVALID_PARAMETER;\r
544 }\r
545\r
8d00a0f1 546 FirstElement = TRUE;\r
547\r
93e3992d 548 //\r
549 // Allocate a fix length of memory to store Results. Reallocate memory for\r
550 // Results if this fix length is insufficient.\r
551 //\r
552 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
553 if (*Results == NULL) {\r
554 return EFI_OUT_OF_RESOURCES;\r
555 }\r
556\r
557 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
558 //\r
559 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
560 // or most recent & before the error.\r
561 //\r
562 if (StringPtr == Request) {\r
563 *Progress = StringPtr;\r
564 } else {\r
565 *Progress = StringPtr - 1;\r
566 }\r
567\r
568 //\r
569 // Process each <ConfigRequest> of <MultiConfigRequest>\r
570 //\r
571 Length = CalculateConfigStringLen (StringPtr);\r
572 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
573 if (ConfigRequest == NULL) {\r
574 return EFI_OUT_OF_RESOURCES;\r
575 }\r
576 *(ConfigRequest + Length) = 0;\r
577\r
578 //\r
579 // Get the UEFI device path\r
580 //\r
581 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
582 if (EFI_ERROR (Status)) {\r
676df92c 583 FreePool (ConfigRequest);\r
93e3992d 584 return Status;\r
585 }\r
586\r
587 //\r
588 // Find driver which matches the routing data.\r
589 //\r
590 DriverHandle = NULL;\r
591 for (Link = Private->DatabaseList.ForwardLink;\r
592 Link != &Private->DatabaseList;\r
593 Link = Link->ForwardLink\r
594 ) {\r
595 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
08e6463a 596 \r
597 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
598 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
93e3992d 599 if (CompareMem (\r
600 DevicePath,\r
601 CurrentDevicePath,\r
602 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
603 ) == 0) {\r
604 DriverHandle = Database->DriverHandle;\r
605 break;\r
606 }\r
607 }\r
608 }\r
609\r
676df92c 610 FreePool (DevicePath);\r
93e3992d 611\r
612 if (DriverHandle == NULL) {\r
613 //\r
614 // Routing data does not match any known driver.\r
615 // Set Progress to the 'G' in "GUID" of the routing header.\r
616 //\r
617 *Progress = StringPtr;\r
676df92c 618 FreePool (ConfigRequest);\r
93e3992d 619 return EFI_NOT_FOUND;\r
620 }\r
621\r
622 //\r
623 // Call corresponding ConfigAccess protocol to extract settings\r
624 //\r
625 Status = gBS->HandleProtocol (\r
626 DriverHandle,\r
627 &gEfiHiiConfigAccessProtocolGuid,\r
628 (VOID **) &ConfigAccess\r
629 );\r
630 ASSERT_EFI_ERROR (Status);\r
631\r
632 Status = ConfigAccess->ExtractConfig (\r
633 ConfigAccess,\r
634 ConfigRequest,\r
635 &AccessProgress,\r
636 &AccessResults\r
637 );\r
638 if (EFI_ERROR (Status)) {\r
639 //\r
640 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
641 // Map it to the progress on <MultiConfigRequest> then return it.\r
642 //\r
8d00a0f1 643 *Progress = StrStr (StringPtr, AccessProgress);\r
676df92c 644 FreePool (ConfigRequest);\r
93e3992d 645 return Status;\r
646 }\r
647\r
648 //\r
8d00a0f1 649 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
650 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 651 //\r
652 ASSERT (*AccessProgress == 0);\r
8d00a0f1 653\r
654 if (!FirstElement) {\r
655 Status = AppendToMultiString (Results, L"&");\r
656 ASSERT_EFI_ERROR (Status);\r
657 }\r
658 \r
93e3992d 659 Status = AppendToMultiString (Results, AccessResults);\r
660 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 661\r
662 FirstElement = FALSE;\r
663 \r
676df92c 664 FreePool (AccessResults);\r
93e3992d 665 AccessResults = NULL;\r
676df92c 666 FreePool (ConfigRequest);\r
93e3992d 667 ConfigRequest = NULL;\r
668\r
669 //\r
670 // Go to next <ConfigRequest> (skip '&').\r
671 //\r
672 StringPtr += Length;\r
673 if (*StringPtr == 0) {\r
674 *Progress = StringPtr;\r
675 break;\r
676 }\r
677\r
678 StringPtr++;\r
679\r
680 }\r
681\r
682 return EFI_SUCCESS;\r
93e3992d 683\r
684}\r
685\r
686\r
687/**\r
688 This function allows the caller to request the current configuration for the\r
689 entirety of the current HII database and returns the data in a\r
690 null-terminated Unicode string.\r
691\r
692 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
693 instance.\r
694 @param Results Null-terminated Unicode string in\r
695 <MultiConfigAltResp> format which has all values\r
696 filled in for the names in the Request string.\r
697 String to be allocated by the called function.\r
698 De-allocation is up to the caller.\r
699\r
700 @retval EFI_SUCCESS The Results string is filled with the values\r
701 corresponding to all requested names.\r
702 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
703 results that must be stored awaiting possible\r
704 future protocols.\r
705 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
706 parameter would result in this type of error.\r
707\r
708**/\r
709EFI_STATUS\r
710EFIAPI\r
711HiiConfigRoutingExportConfig (\r
712 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
713 OUT EFI_STRING *Results\r
714 )\r
715{\r
93e3992d 716 EFI_STATUS Status;\r
93e3992d 717 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
8d00a0f1 718 EFI_STRING AccessResults; \r
719 UINTN Index;\r
720 EFI_HANDLE *ConfigAccessHandles;\r
721 UINTN NumberConfigAccessHandles;\r
722 BOOLEAN FirstElement;\r
93e3992d 723\r
724 if (This == NULL || Results == NULL) {\r
725 return EFI_INVALID_PARAMETER;\r
726 }\r
727\r
93e3992d 728 //\r
729 // Allocate a fix length of memory to store Results. Reallocate memory for\r
730 // Results if this fix length is insufficient.\r
731 //\r
732 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
733 if (*Results == NULL) {\r
734 return EFI_OUT_OF_RESOURCES;\r
735 }\r
736\r
8d00a0f1 737 NumberConfigAccessHandles = 0;\r
738 Status = gBS->LocateHandleBuffer (\r
739 ByProtocol,\r
740 &gEfiHiiConfigAccessProtocolGuid,\r
741 NULL,\r
742 &NumberConfigAccessHandles,\r
743 &ConfigAccessHandles\r
744 );\r
745 if (EFI_ERROR (Status)) {\r
746 return Status;\r
747 }\r
93e3992d 748\r
8d00a0f1 749 FirstElement = TRUE;\r
93e3992d 750\r
8d00a0f1 751 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 752 Status = gBS->HandleProtocol (\r
8d00a0f1 753 ConfigAccessHandles[Index],\r
93e3992d 754 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 755 (VOID **) &ConfigAccess\r
93e3992d 756 );\r
8d00a0f1 757 if (EFI_ERROR (Status)) {\r
758 continue;\r
759 }\r
93e3992d 760\r
761 Status = ConfigAccess->ExtractConfig (\r
762 ConfigAccess,\r
8d00a0f1 763 NULL,\r
764 NULL,\r
93e3992d 765 &AccessResults\r
766 );\r
8d00a0f1 767 if (!EFI_ERROR (Status)) {\r
768 //\r
769 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
770 // which seperates the first <ConfigAltResp> and the following ones. \r
771 //\r
772 if (!FirstElement) {\r
773 Status = AppendToMultiString (Results, L"&");\r
774 ASSERT_EFI_ERROR (Status);\r
676df92c 775 }\r
8d00a0f1 776 \r
777 Status = AppendToMultiString (Results, AccessResults);\r
778 ASSERT_EFI_ERROR (Status);\r
93e3992d 779\r
8d00a0f1 780 FirstElement = FALSE;\r
781 \r
782 FreePool (AccessResults);\r
783 AccessResults = NULL;\r
784 }\r
93e3992d 785 }\r
f4113e1f 786 FreePool (ConfigAccessHandles);\r
93e3992d 787\r
8d00a0f1 788 return EFI_SUCCESS; \r
93e3992d 789}\r
790\r
791\r
792/**\r
793 This function processes the results of processing forms and routes it to the\r
794 appropriate handlers or storage.\r
795\r
796 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
797 instance.\r
798 @param Configuration A null-terminated Unicode string in\r
799 <MulltiConfigResp> format.\r
800 @param Progress A pointer to a string filled in with the offset of\r
801 the most recent & before the first failing name /\r
802 value pair (or the beginning of the string if the\r
803 failure is in the first name / value pair) or the\r
804 terminating NULL if all was successful.\r
805\r
806 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
807 distribution.\r
808 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
809 results that must be stored awaiting possible\r
810 future protocols.\r
811 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
812 would result in this type of error.\r
813 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
814 found.\r
815\r
816**/\r
817EFI_STATUS\r
818EFIAPI\r
813acf3a 819HiiConfigRoutingRouteConfig (\r
93e3992d 820 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
821 IN CONST EFI_STRING Configuration,\r
822 OUT EFI_STRING *Progress\r
823 )\r
824{\r
93e3992d 825 HII_DATABASE_PRIVATE_DATA *Private;\r
826 EFI_STRING StringPtr;\r
827 EFI_STRING ConfigResp;\r
828 UINTN Length;\r
829 EFI_STATUS Status;\r
830 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
831 LIST_ENTRY *Link;\r
832 HII_DATABASE_RECORD *Database;\r
08e6463a 833 UINT8 *DevicePathPkg;\r
93e3992d 834 UINT8 *CurrentDevicePath;\r
835 EFI_HANDLE DriverHandle;\r
836 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
837 EFI_STRING AccessProgress;\r
93e3992d 838\r
839 if (This == NULL || Progress == NULL) {\r
840 return EFI_INVALID_PARAMETER;\r
841 }\r
842\r
843 if (Configuration == NULL) {\r
844 *Progress = NULL;\r
845 return EFI_INVALID_PARAMETER;\r
846 }\r
847\r
848 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
849 StringPtr = Configuration;\r
850 *Progress = StringPtr;\r
851\r
852 //\r
853 // The first element of <MultiConfigResp> should be\r
854 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
855 //\r
856 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
857 return EFI_INVALID_PARAMETER;\r
858 }\r
859\r
860 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
861 //\r
862 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
863 // or most recent & before the error.\r
864 //\r
865 if (StringPtr == Configuration) {\r
866 *Progress = StringPtr;\r
867 } else {\r
868 *Progress = StringPtr - 1;\r
869 }\r
870\r
871 //\r
872 // Process each <ConfigResp> of <MultiConfigResp>\r
873 //\r
874 Length = CalculateConfigStringLen (StringPtr);\r
875 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
876 if (ConfigResp == NULL) {\r
877 return EFI_OUT_OF_RESOURCES;\r
878 }\r
879 //\r
880 // Append '\0' to the end of ConfigRequest\r
881 //\r
882 *(ConfigResp + Length) = 0;\r
883\r
884 //\r
885 // Get the UEFI device path\r
886 //\r
887 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
888 if (EFI_ERROR (Status)) {\r
676df92c 889 FreePool (ConfigResp);\r
93e3992d 890 return Status;\r
891 }\r
892\r
893 //\r
894 // Find driver which matches the routing data.\r
895 //\r
896 DriverHandle = NULL;\r
897 for (Link = Private->DatabaseList.ForwardLink;\r
898 Link != &Private->DatabaseList;\r
899 Link = Link->ForwardLink\r
900 ) {\r
901 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
08e6463a 902\r
903 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
904 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
93e3992d 905 if (CompareMem (\r
906 DevicePath,\r
907 CurrentDevicePath,\r
908 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
909 ) == 0) {\r
910 DriverHandle = Database->DriverHandle;\r
911 break;\r
912 }\r
913 }\r
914 }\r
915\r
676df92c 916 FreePool (DevicePath);\r
93e3992d 917\r
918 if (DriverHandle == NULL) {\r
919 //\r
920 // Routing data does not match any known driver.\r
921 // Set Progress to the 'G' in "GUID" of the routing header.\r
922 //\r
923 *Progress = StringPtr;\r
676df92c 924 FreePool (ConfigResp);\r
93e3992d 925 return EFI_NOT_FOUND;\r
926 }\r
927\r
928 //\r
929 // Call corresponding ConfigAccess protocol to route settings\r
930 //\r
931 Status = gBS->HandleProtocol (\r
932 DriverHandle,\r
933 &gEfiHiiConfigAccessProtocolGuid,\r
934 (VOID **) &ConfigAccess\r
935 );\r
936 ASSERT_EFI_ERROR (Status);\r
937\r
938 Status = ConfigAccess->RouteConfig (\r
939 ConfigAccess,\r
940 ConfigResp,\r
941 &AccessProgress\r
942 );\r
943\r
944 if (EFI_ERROR (Status)) {\r
945 //\r
946 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
947 // Map it to the progress on <MultiConfigResp> then return it.\r
948 //\r
8d00a0f1 949 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 950\r
676df92c 951 FreePool (ConfigResp);\r
93e3992d 952 return Status;\r
953 }\r
954\r
676df92c 955 FreePool (ConfigResp);\r
93e3992d 956 ConfigResp = NULL;\r
957\r
958 //\r
959 // Go to next <ConfigResp> (skip '&').\r
960 //\r
961 StringPtr += Length;\r
962 if (*StringPtr == 0) {\r
963 *Progress = StringPtr;\r
964 break;\r
965 }\r
966\r
967 StringPtr++;\r
968\r
969 }\r
970\r
971 return EFI_SUCCESS;\r
93e3992d 972}\r
973\r
974\r
975/**\r
976 This helper function is to be called by drivers to map configuration data\r
977 stored in byte array ("block") formats such as UEFI Variables into current\r
978 configuration strings.\r
979\r
980 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
981 instance.\r
982 @param ConfigRequest A null-terminated Unicode string in\r
983 <ConfigRequest> format.\r
984 @param Block Array of bytes defining the block's configuration.\r
985 @param BlockSize Length in bytes of Block.\r
986 @param Config Filled-in configuration string. String allocated\r
987 by the function. Returned only if call is\r
988 successful.\r
989 @param Progress A pointer to a string filled in with the offset of\r
990 the most recent & before the first failing\r
991 name/value pair (or the beginning of the string if\r
992 the failure is in the first name / value pair) or\r
993 the terminating NULL if all was successful.\r
994\r
995 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
996 terminator at the end of the ConfigRequest\r
997 string.\r
998 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
999 points to the first character of ConfigRequest.\r
1000 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
1001 Block parameter would result in this type of\r
1002 error. Progress points to the first character of\r
1003 ConfigRequest.\r
1004 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
1005 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
1006 Block is left updated and Progress points at\r
1007 the "&" preceding the first non-<BlockName>.\r
1008\r
1009**/\r
1010EFI_STATUS\r
1011EFIAPI\r
1012HiiBlockToConfig (\r
1013 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1014 IN CONST EFI_STRING ConfigRequest,\r
1015 IN CONST UINT8 *Block,\r
1016 IN CONST UINTN BlockSize,\r
1017 OUT EFI_STRING *Config,\r
1018 OUT EFI_STRING *Progress\r
1019 )\r
1020{\r
1021 HII_DATABASE_PRIVATE_DATA *Private;\r
1022 EFI_STRING StringPtr;\r
1023 UINTN Length;\r
1024 EFI_STATUS Status;\r
1025 EFI_STRING TmpPtr;\r
1026 UINT8 *TmpBuffer;\r
1027 UINTN Offset;\r
1028 UINTN Width;\r
1029 UINT8 *Value;\r
1030 EFI_STRING ValueStr;\r
1031 EFI_STRING ConfigElement;\r
63d55bb9
LG
1032 UINTN Index;\r
1033 UINT8 *TemBuffer;\r
1034 CHAR16 *TemString;\r
93e3992d 1035\r
1036 if (This == NULL || Progress == NULL || Config == NULL) {\r
1037 return EFI_INVALID_PARAMETER;\r
1038 }\r
1039\r
1040 if (Block == NULL || ConfigRequest == NULL) {\r
1041 *Progress = ConfigRequest;\r
1042 return EFI_INVALID_PARAMETER;\r
1043 }\r
1044\r
1045\r
1046 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1047 ASSERT (Private != NULL);\r
1048\r
1049 StringPtr = ConfigRequest;\r
1050 ValueStr = NULL;\r
1051 Value = NULL;\r
1052 ConfigElement = NULL;\r
1053\r
1054 //\r
1055 // Allocate a fix length of memory to store Results. Reallocate memory for\r
1056 // Results if this fix length is insufficient.\r
1057 //\r
1058 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
1059 if (*Config == NULL) {\r
1060 return EFI_OUT_OF_RESOURCES;\r
1061 }\r
1062\r
1063 //\r
1064 // Jump <ConfigHdr>\r
1065 //\r
1066 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1067 *Progress = StringPtr;\r
1068 Status = EFI_INVALID_PARAMETER;\r
1069 goto Exit;\r
1070 }\r
1071 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1072 StringPtr++;\r
1073 }\r
1074 if (*StringPtr == 0) {\r
1075 *Progress = StringPtr;\r
1076 Status = EFI_INVALID_PARAMETER;\r
1077 goto Exit;\r
1078 }\r
08e6463a 1079\r
1080 while (*StringPtr != L'&' && *StringPtr != 0) {\r
1081 StringPtr++;\r
1082 }\r
1083 if (*StringPtr == 0) {\r
1084 *Progress = StringPtr;\r
1085 Status = EFI_INVALID_PARAMETER;\r
1086 goto Exit;\r
1087 }\r
1088 //\r
1089 // Skip '&'\r
1090 //\r
1091 StringPtr++;\r
93e3992d 1092\r
1093 //\r
1094 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
1095 //\r
1096 Length = StringPtr - ConfigRequest;\r
1097 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
1098\r
1099 //\r
1100 // Parse each <RequestElement> if exists\r
1101 // Only <BlockName> format is supported by this help function.\r
1102 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
1103 //\r
1104 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1105 //\r
1106 // Back up the header of one <BlockName>\r
1107 //\r
1108 TmpPtr = StringPtr;\r
1109\r
1110 StringPtr += StrLen (L"OFFSET=");\r
1111 //\r
1112 // Get Offset\r
1113 //\r
1114 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1115 if (Status == EFI_OUT_OF_RESOURCES) {\r
1116 *Progress = ConfigRequest;\r
1117 goto Exit;\r
1118 }\r
1119 Offset = 0;\r
1120 CopyMem (\r
1121 &Offset,\r
1122 TmpBuffer,\r
1123 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1124 );\r
676df92c 1125 FreePool (TmpBuffer);\r
93e3992d 1126\r
1127 StringPtr += Length;\r
1128 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1129 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1130 Status = EFI_INVALID_PARAMETER;\r
1131 goto Exit;\r
1132 }\r
1133 StringPtr += StrLen (L"&WIDTH=");\r
1134\r
1135 //\r
1136 // Get Width\r
1137 //\r
1138 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1139 if (Status == EFI_OUT_OF_RESOURCES) {\r
1140 *Progress = ConfigRequest;\r
1141 goto Exit;\r
1142 }\r
1143 Width = 0;\r
1144 CopyMem (\r
1145 &Width,\r
1146 TmpBuffer,\r
1147 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1148 );\r
676df92c 1149 FreePool (TmpBuffer);\r
93e3992d 1150\r
1151 StringPtr += Length;\r
1152 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1153 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1154 Status = EFI_INVALID_PARAMETER;\r
1155 goto Exit;\r
1156 }\r
1157\r
1158 //\r
1159 // Calculate Value and convert it to hex string.\r
1160 //\r
1161 if (Offset + Width > BlockSize) {\r
1162 *Progress = StringPtr;\r
1163 Status = EFI_DEVICE_ERROR;\r
1164 goto Exit;\r
1165 }\r
1166\r
1167 Value = (UINT8 *) AllocateZeroPool (Width);\r
1168 if (Value == NULL) {\r
1169 *Progress = ConfigRequest;\r
1170 Status = EFI_OUT_OF_RESOURCES;\r
1171 goto Exit;\r
1172 }\r
1173\r
1174 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
1175\r
1176 Length = Width * 2 + 1;\r
1177 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1178 if (ValueStr == NULL) {\r
1179 *Progress = ConfigRequest;\r
1180 Status = EFI_OUT_OF_RESOURCES;\r
1181 goto Exit;\r
1182 }\r
63d55bb9
LG
1183 \r
1184 TemString = ValueStr;\r
1185 TemBuffer = Value + Width - 1;\r
1186 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
1187 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1188 }\r
1189 HiiToLower (ValueStr);\r
813acf3a 1190\r
676df92c 1191 FreePool (Value);\r
93e3992d 1192 Value = NULL;\r
1193\r
1194 //\r
1195 // Build a ConfigElement\r
1196 //\r
1197 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
1198 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1199 if (ConfigElement == NULL) {\r
1200 Status = EFI_OUT_OF_RESOURCES;\r
1201 goto Exit;\r
1202 }\r
1203 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
1204 if (*StringPtr == 0) {\r
1205 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
1206 }\r
1207 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
1208 StrCat (ConfigElement, L"VALUE=");\r
1209 StrCat (ConfigElement, ValueStr);\r
1210\r
1211 AppendToMultiString (Config, ConfigElement);\r
1212\r
676df92c 1213 FreePool (ConfigElement);\r
1214 FreePool (ValueStr);\r
93e3992d 1215 ConfigElement = NULL;\r
1216 ValueStr = NULL;\r
1217\r
1218 //\r
1219 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1220 //\r
1221 if (*StringPtr == 0) {\r
1222 break;\r
1223 }\r
1224 AppendToMultiString (Config, L"&");\r
1225 StringPtr++;\r
1226\r
1227 }\r
1228\r
1229 if (*StringPtr != 0) {\r
1230 *Progress = StringPtr - 1;\r
1231 Status = EFI_INVALID_PARAMETER;\r
1232 goto Exit;\r
1233 }\r
1234\r
1235 *Progress = StringPtr;\r
1236 return EFI_SUCCESS;\r
1237\r
1238Exit:\r
676df92c 1239 FreePool (*Config);\r
1240 if (ValueStr != NULL) {\r
1241 FreePool (ValueStr);\r
1242 }\r
1243 if (Value != NULL) {\r
1244 FreePool (Value);\r
1245 }\r
69367b5b 1246 if (ConfigElement != NULL) {\r
676df92c 1247 FreePool (ConfigElement);\r
1248 }\r
93e3992d 1249\r
1250 return Status;\r
1251\r
1252}\r
1253\r
1254\r
1255/**\r
1256 This helper function is to be called by drivers to map configuration strings\r
1257 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
1258\r
1259 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1260 instance.\r
1261 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
1262 format.\r
1263 @param Block A possibly null array of bytes representing the\r
1264 current block. Only bytes referenced in the\r
1265 ConfigResp string in the block are modified. If\r
1266 this parameter is null or if the *BlockSize\r
1267 parameter is (on input) shorter than required by\r
1268 the Configuration string, only the BlockSize\r
1269 parameter is updated and an appropriate status\r
1270 (see below) is returned.\r
1271 @param BlockSize The length of the Block in units of UINT8. On\r
1272 input, this is the size of the Block. On output,\r
1273 if successful, contains the index of the last\r
1274 modified byte in the Block.\r
1275 @param Progress On return, points to an element of the ConfigResp\r
1276 string filled in with the offset of the most\r
1277 recent '&' before the first failing name / value\r
1278 pair (or the beginning of the string if the\r
1279 failure is in the first name / value pair) or the\r
1280 terminating NULL if all was successful.\r
1281\r
1282 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
1283 terminator at the end of the ConfigResp string.\r
1284 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
1285 points to the first character of ConfigResp.\r
1286 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
1287 Block parameter would result in this type of\r
1288 error. Progress points to the first character of\r
1289 ConfigResp.\r
1290 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
1291 value pair. Block is left updated and\r
1292 Progress points at the '&' preceding the first\r
1293 non-<BlockName>.\r
1294\r
1295**/\r
1296EFI_STATUS\r
1297EFIAPI\r
1298HiiConfigToBlock (\r
1299 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1300 IN CONST EFI_STRING ConfigResp,\r
1301 IN OUT UINT8 *Block,\r
1302 IN OUT UINTN *BlockSize,\r
1303 OUT EFI_STRING *Progress\r
1304 )\r
1305{\r
1306 HII_DATABASE_PRIVATE_DATA *Private;\r
1307 EFI_STRING StringPtr;\r
1308 UINTN Length;\r
1309 EFI_STATUS Status;\r
1310 UINT8 *TmpBuffer;\r
1311 UINTN Offset;\r
1312 UINTN Width;\r
1313 UINT8 *Value;\r
1314 UINTN BufferSize;\r
1315\r
1316 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
1317 return EFI_INVALID_PARAMETER;\r
1318 }\r
1319\r
1320 if (ConfigResp == NULL || Block == NULL) {\r
1321 *Progress = ConfigResp;\r
1322 return EFI_INVALID_PARAMETER;\r
1323 }\r
1324\r
1325 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1326 ASSERT (Private != NULL);\r
1327\r
1328 StringPtr = ConfigResp;\r
1329 BufferSize = *BlockSize;\r
1330 Value = NULL;\r
1331\r
1332 //\r
1333 // Jump <ConfigHdr>\r
1334 //\r
1335 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1336 *Progress = StringPtr;\r
1337 Status = EFI_INVALID_PARAMETER;\r
1338 goto Exit;\r
1339 }\r
1340 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1341 StringPtr++;\r
1342 }\r
1343 if (*StringPtr == 0) {\r
1344 *Progress = StringPtr;\r
1345 Status = EFI_INVALID_PARAMETER;\r
1346 goto Exit;\r
1347 }\r
08e6463a 1348\r
1349 while (*StringPtr != L'&' && *StringPtr != 0) {\r
1350 StringPtr++;\r
1351 }\r
1352 if (*StringPtr == 0) {\r
1353 *Progress = StringPtr;\r
1354 Status = EFI_INVALID_PARAMETER;\r
1355 goto Exit;\r
1356 }\r
1357 //\r
1358 // Skip '&'\r
1359 //\r
1360 StringPtr++;\r
93e3992d 1361\r
1362 //\r
1363 // Parse each <ConfigElement> if exists\r
1364 // Only <BlockConfig> format is supported by this help function.\r
1365 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
1366 //\r
1367 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1368 StringPtr += StrLen (L"OFFSET=");\r
1369 //\r
1370 // Get Offset\r
1371 //\r
1372 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 1373 if (EFI_ERROR (Status)) {\r
93e3992d 1374 *Progress = ConfigResp;\r
1375 goto Exit;\r
1376 }\r
1377 Offset = 0;\r
1378 CopyMem (\r
1379 &Offset,\r
1380 TmpBuffer,\r
1381 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1382 );\r
676df92c 1383 FreePool (TmpBuffer);\r
93e3992d 1384\r
1385 StringPtr += Length;\r
1386 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1387 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1388 Status = EFI_INVALID_PARAMETER;\r
1389 goto Exit;\r
1390 }\r
1391 StringPtr += StrLen (L"&WIDTH=");\r
1392\r
1393 //\r
1394 // Get Width\r
1395 //\r
1396 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1397 if (Status == EFI_OUT_OF_RESOURCES) {\r
1398 *Progress = ConfigResp;\r
1399 goto Exit;\r
1400 }\r
1401 Width = 0;\r
1402 CopyMem (\r
1403 &Width,\r
1404 TmpBuffer,\r
1405 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1406 );\r
676df92c 1407 FreePool (TmpBuffer);\r
93e3992d 1408\r
1409 StringPtr += Length;\r
1410 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
1411 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1412 Status = EFI_INVALID_PARAMETER;\r
1413 goto Exit;\r
1414 }\r
1415 StringPtr += StrLen (L"&VALUE=");\r
1416\r
1417 //\r
1418 // Get Value\r
1419 //\r
1420 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 1421 if (EFI_ERROR (Status)) {\r
93e3992d 1422 *Progress = ConfigResp;\r
1423 goto Exit;\r
1424 }\r
1425\r
1426 StringPtr += Length;\r
1427 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1428 *Progress = StringPtr - Length - 7;\r
1429 Status = EFI_INVALID_PARAMETER;\r
1430 goto Exit;\r
1431 }\r
1432\r
1433 //\r
1434 // Update the Block with configuration info\r
1435 //\r
1436\r
1437 if (Offset + Width > BufferSize) {\r
1438 return EFI_DEVICE_ERROR;\r
1439 }\r
1440\r
1441 CopyMem (Block + Offset, Value, Width);\r
1442 *BlockSize = Offset + Width - 1;\r
1443\r
676df92c 1444 FreePool (Value);\r
93e3992d 1445 Value = NULL;\r
1446\r
1447 //\r
1448 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1449 //\r
1450 if (*StringPtr == 0) {\r
1451 break;\r
1452 }\r
1453\r
1454 StringPtr++;\r
1455 }\r
1456\r
1457 if (*StringPtr != 0) {\r
1458 *Progress = StringPtr - 1;\r
1459 Status = EFI_INVALID_PARAMETER;\r
1460 goto Exit;\r
1461 }\r
1462\r
1463 *Progress = StringPtr;\r
1464 return EFI_SUCCESS;\r
1465\r
1466Exit:\r
1467\r
676df92c 1468 if (Value != NULL) {\r
1469 FreePool (Value);\r
1470 }\r
93e3992d 1471 return Status;\r
1472}\r
1473\r
1474\r
1475/**\r
1476 This helper function is to be called by drivers to extract portions of\r
1477 a larger configuration string.\r
1478\r
1479 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1480 instance.\r
1481 @param Configuration A null-terminated Unicode string in\r
1482 <MultiConfigAltResp> format.\r
1483 @param Guid A pointer to the GUID value to search for in the\r
1484 routing portion of the ConfigResp string when\r
1485 retrieving the requested data. If Guid is NULL,\r
1486 then all GUID values will be searched for.\r
1487 @param Name A pointer to the NAME value to search for in the\r
1488 routing portion of the ConfigResp string when\r
1489 retrieving the requested data. If Name is NULL,\r
1490 then all Name values will be searched for.\r
1491 @param DevicePath A pointer to the PATH value to search for in the\r
1492 routing portion of the ConfigResp string when\r
1493 retrieving the requested data. If DevicePath is\r
1494 NULL, then all DevicePath values will be searched\r
1495 for.\r
1496 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
1497 routing portion of the ConfigResp string when\r
1498 retrieving the requested data. If this parameter\r
1499 is NULL, then the current setting will be\r
1500 retrieved.\r
1501 @param AltCfgResp A pointer to a buffer which will be allocated by\r
1502 the function which contains the retrieved string\r
1503 as requested. This buffer is only allocated if\r
1504 the call was successful.\r
1505\r
1506 @retval EFI_SUCCESS The request succeeded. The requested data was\r
1507 extracted and placed in the newly allocated\r
1508 AltCfgResp buffer.\r
1509 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
1510 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
1511 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
1512 found.\r
1513\r
1514**/\r
1515EFI_STATUS\r
1516EFIAPI\r
1517HiiGetAltCfg (\r
1518 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1519 IN CONST EFI_STRING Configuration,\r
1520 IN CONST EFI_GUID *Guid,\r
1521 IN CONST EFI_STRING Name,\r
1522 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1523 IN CONST UINT16 *AltCfgId,\r
1524 OUT EFI_STRING *AltCfgResp\r
1525 )\r
1526{\r
93e3992d 1527 EFI_STATUS Status;\r
1528 EFI_STRING StringPtr;\r
e90b081a 1529 EFI_STRING HdrStart;\r
1530 EFI_STRING HdrEnd;\r
93e3992d 1531 EFI_STRING TmpPtr;\r
1532 UINTN Length;\r
e90b081a 1533 EFI_STRING GuidStr;\r
1534 EFI_STRING NameStr;\r
1535 EFI_STRING PathStr;\r
1536 EFI_STRING AltIdStr;\r
1537 EFI_STRING Result;\r
1538 BOOLEAN GuidFlag;\r
1539 BOOLEAN NameFlag;\r
1540 BOOLEAN PathFlag;\r
1541\r
1542 HdrStart = NULL;\r
1543 HdrEnd = NULL;\r
1544 GuidStr = NULL;\r
1545 NameStr = NULL;\r
1546 PathStr = NULL;\r
1547 AltIdStr = NULL;\r
1548 Result = NULL;\r
1549 GuidFlag = FALSE;\r
1550 NameFlag = FALSE;\r
1551 PathFlag = FALSE;\r
93e3992d 1552\r
1553 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
1554 return EFI_INVALID_PARAMETER;\r
1555 }\r
1556\r
1557 StringPtr = Configuration;\r
1558 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1559 return EFI_INVALID_PARAMETER;\r
1560 }\r
1561\r
1562 //\r
1563 // Generate the sub string for later matching.\r
1564 //\r
813acf3a 1565 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 1566 GenerateSubStr (\r
1567 L"PATH=",\r
1568 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 1569 (VOID *) DevicePath,\r
1570 1,\r
93e3992d 1571 &PathStr\r
1572 );\r
1573 if (AltCfgId != NULL) {\r
813acf3a 1574 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 1575 }\r
1576 if (Name != NULL) {\r
813acf3a 1577 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 1578 } else {\r
813acf3a 1579 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 1580 }\r
1581\r
1582 while (*StringPtr != 0) {\r
1583 //\r
1584 // Try to match the GUID\r
1585 //\r
1586 if (!GuidFlag) {\r
1587 TmpPtr = StrStr (StringPtr, GuidStr);\r
1588 if (TmpPtr == NULL) {\r
1589 Status = EFI_NOT_FOUND;\r
1590 goto Exit;\r
1591 }\r
1592 HdrStart = TmpPtr;\r
1593\r
1594 //\r
1595 // Jump to <NameHdr>\r
1596 //\r
1597 if (Guid != NULL) {\r
1598 StringPtr = TmpPtr + StrLen (GuidStr);\r
1599 } else {\r
1600 StringPtr = StrStr (TmpPtr, L"NAME=");\r
1601 if (StringPtr == NULL) {\r
1602 Status = EFI_NOT_FOUND;\r
1603 goto Exit;\r
1604 }\r
1605 }\r
1606 GuidFlag = TRUE;\r
1607 }\r
1608\r
1609 //\r
1610 // Try to match the NAME\r
1611 //\r
1612 if (GuidFlag && !NameFlag) {\r
1613 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
1614 GuidFlag = FALSE;\r
1615 } else {\r
1616 //\r
1617 // Jump to <PathHdr>\r
1618 //\r
1619 if (Name != NULL) {\r
1620 StringPtr += StrLen (NameStr);\r
1621 } else {\r
1622 StringPtr = StrStr (StringPtr, L"PATH=");\r
1623 if (StringPtr == NULL) {\r
1624 Status = EFI_NOT_FOUND;\r
1625 goto Exit;\r
1626 }\r
1627 }\r
1628 NameFlag = TRUE;\r
1629 }\r
1630 }\r
1631\r
1632 //\r
1633 // Try to match the DevicePath\r
1634 //\r
1635 if (GuidFlag && NameFlag && !PathFlag) {\r
1636 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
1637 GuidFlag = FALSE;\r
1638 NameFlag = FALSE;\r
1639 } else {\r
1640 //\r
1641 // Jump to '&' before <DescHdr> or <ConfigBody>\r
1642 //\r
1643 if (DevicePath != NULL) {\r
1644 StringPtr += StrLen (PathStr);\r
1645 } else {\r
1646 StringPtr = StrStr (StringPtr, L"&");\r
1647 if (StringPtr == NULL) {\r
1648 Status = EFI_NOT_FOUND;\r
1649 goto Exit;\r
1650 }\r
1651 }\r
1652 PathFlag = TRUE;\r
1653 HdrEnd = ++StringPtr;\r
1654 }\r
1655 }\r
1656\r
1657 //\r
1658 // Try to match the AltCfgId\r
1659 //\r
1660 if (GuidFlag && NameFlag && PathFlag) {\r
1661 if (AltCfgId == NULL) {\r
1662 //\r
1663 // Return Current Setting when AltCfgId is NULL.\r
1664 //\r
1665 Status = OutputConfigBody (StringPtr, &Result);\r
1666 goto Exit;\r
1667 }\r
1668 //\r
1669 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
1670 //\r
1671 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
1672 GuidFlag = FALSE;\r
1673 NameFlag = FALSE;\r
1674 PathFlag = FALSE;\r
1675 } else {\r
1676 Status = OutputConfigBody (StringPtr, &Result);\r
1677 goto Exit;\r
1678 }\r
1679 }\r
1680 }\r
1681\r
1682 Status = EFI_NOT_FOUND;\r
1683\r
1684Exit:\r
1685\r
bc166db3 1686 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 1687 //\r
1688 // Copy the <ConfigHdr> and <ConfigBody>\r
1689 //\r
1690 Length = HdrEnd - HdrStart + StrLen (Result);\r
1691 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
1692 if (*AltCfgResp == NULL) {\r
1693 Status = EFI_OUT_OF_RESOURCES;\r
1694 } else {\r
1695 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
1696 StrCat (*AltCfgResp, Result);\r
1697 Status = EFI_SUCCESS;\r
1698 }\r
1699 }\r
1700\r
676df92c 1701 if (GuidStr != NULL) {\r
1702 FreePool (GuidStr);\r
1703 }\r
1704 if (NameStr != NULL) {\r
1705 FreePool (NameStr);\r
1706 }\r
1707 if (PathStr != NULL) {\r
1708 FreePool (PathStr);\r
1709 }\r
1710 if (AltIdStr != NULL) {\r
1711 FreePool (AltIdStr);\r
1712 }\r
1713 if (Result != NULL) {\r
1714 FreePool (Result);\r
1715 }\r
93e3992d 1716\r
1717 return Status;\r
1718\r
93e3992d 1719}\r
1720\r
36fe40c2 1721\r