]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
1. Add address check for "RegisterForRuntime" APIs of PciLib, PciCf8Lib, PciExpressLi...
[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
326c6b71 4Copyright (c) 2007 - 2009, 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 EFI_STRING StringPtr;\r
510 EFI_STRING ConfigRequest;\r
511 UINTN Length;\r
512 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 513 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 514 EFI_STATUS Status;\r
93e3992d 515 EFI_HANDLE DriverHandle;\r
516 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
517 EFI_STRING AccessProgress;\r
518 EFI_STRING AccessResults;\r
8d00a0f1 519 BOOLEAN FirstElement;\r
93e3992d 520\r
521 if (This == NULL || Progress == NULL || Results == NULL) {\r
522 return EFI_INVALID_PARAMETER;\r
523 }\r
524\r
525 if (Request == NULL) {\r
526 *Progress = NULL;\r
527 return EFI_INVALID_PARAMETER;\r
528 }\r
529\r
93e3992d 530 StringPtr = Request;\r
531 *Progress = StringPtr;\r
532\r
533 //\r
534 // The first element of <MultiConfigRequest> should be\r
535 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
536 //\r
537 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540\r
8d00a0f1 541 FirstElement = TRUE;\r
542\r
93e3992d 543 //\r
544 // Allocate a fix length of memory to store Results. Reallocate memory for\r
545 // Results if this fix length is insufficient.\r
546 //\r
547 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
548 if (*Results == NULL) {\r
549 return EFI_OUT_OF_RESOURCES;\r
550 }\r
551\r
552 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
553 //\r
554 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
555 // or most recent & before the error.\r
556 //\r
557 if (StringPtr == Request) {\r
558 *Progress = StringPtr;\r
559 } else {\r
560 *Progress = StringPtr - 1;\r
561 }\r
562\r
563 //\r
564 // Process each <ConfigRequest> of <MultiConfigRequest>\r
565 //\r
566 Length = CalculateConfigStringLen (StringPtr);\r
567 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
568 if (ConfigRequest == NULL) {\r
569 return EFI_OUT_OF_RESOURCES;\r
570 }\r
571 *(ConfigRequest + Length) = 0;\r
572\r
573 //\r
574 // Get the UEFI device path\r
575 //\r
576 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
577 if (EFI_ERROR (Status)) {\r
676df92c 578 FreePool (ConfigRequest);\r
93e3992d 579 return Status;\r
580 }\r
581\r
582 //\r
326c6b71 583 // Find driver handle by device path\r
93e3992d 584 //\r
585 DriverHandle = NULL;\r
326c6b71 586 TempDevicePath = DevicePath;\r
587 Status = gBS->LocateDevicePath (\r
588 &gEfiDevicePathProtocolGuid,\r
589 &TempDevicePath,\r
590 &DriverHandle\r
591 );\r
676df92c 592 FreePool (DevicePath);\r
93e3992d 593\r
326c6b71 594 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
93e3992d 595 //\r
326c6b71 596 // Cannot find any known driver.\r
93e3992d 597 // Set Progress to the 'G' in "GUID" of the routing header.\r
598 //\r
599 *Progress = StringPtr;\r
676df92c 600 FreePool (ConfigRequest);\r
93e3992d 601 return EFI_NOT_FOUND;\r
602 }\r
603\r
604 //\r
605 // Call corresponding ConfigAccess protocol to extract settings\r
606 //\r
607 Status = gBS->HandleProtocol (\r
608 DriverHandle,\r
609 &gEfiHiiConfigAccessProtocolGuid,\r
610 (VOID **) &ConfigAccess\r
611 );\r
612 ASSERT_EFI_ERROR (Status);\r
613\r
614 Status = ConfigAccess->ExtractConfig (\r
615 ConfigAccess,\r
616 ConfigRequest,\r
617 &AccessProgress,\r
618 &AccessResults\r
619 );\r
620 if (EFI_ERROR (Status)) {\r
621 //\r
622 // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
623 // Map it to the progress on <MultiConfigRequest> then return it.\r
624 //\r
8d00a0f1 625 *Progress = StrStr (StringPtr, AccessProgress);\r
676df92c 626 FreePool (ConfigRequest);\r
93e3992d 627 return Status;\r
628 }\r
629\r
630 //\r
8d00a0f1 631 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
632 // which seperates the first <ConfigAltResp> and the following ones.\r
93e3992d 633 //\r
634 ASSERT (*AccessProgress == 0);\r
8d00a0f1 635\r
636 if (!FirstElement) {\r
637 Status = AppendToMultiString (Results, L"&");\r
638 ASSERT_EFI_ERROR (Status);\r
639 }\r
640 \r
93e3992d 641 Status = AppendToMultiString (Results, AccessResults);\r
642 ASSERT_EFI_ERROR (Status);\r
8d00a0f1 643\r
644 FirstElement = FALSE;\r
645 \r
676df92c 646 FreePool (AccessResults);\r
93e3992d 647 AccessResults = NULL;\r
676df92c 648 FreePool (ConfigRequest);\r
93e3992d 649 ConfigRequest = NULL;\r
650\r
651 //\r
652 // Go to next <ConfigRequest> (skip '&').\r
653 //\r
654 StringPtr += Length;\r
655 if (*StringPtr == 0) {\r
656 *Progress = StringPtr;\r
657 break;\r
658 }\r
659\r
660 StringPtr++;\r
661\r
662 }\r
663\r
664 return EFI_SUCCESS;\r
93e3992d 665\r
666}\r
667\r
668\r
669/**\r
670 This function allows the caller to request the current configuration for the\r
671 entirety of the current HII database and returns the data in a\r
672 null-terminated Unicode string.\r
673\r
674 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
675 instance.\r
676 @param Results Null-terminated Unicode string in\r
677 <MultiConfigAltResp> format which has all values\r
678 filled in for the names in the Request string.\r
679 String to be allocated by the called function.\r
680 De-allocation is up to the caller.\r
681\r
682 @retval EFI_SUCCESS The Results string is filled with the values\r
683 corresponding to all requested names.\r
684 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
685 results that must be stored awaiting possible\r
686 future protocols.\r
687 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
688 parameter would result in this type of error.\r
689\r
690**/\r
691EFI_STATUS\r
692EFIAPI\r
693HiiConfigRoutingExportConfig (\r
694 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
695 OUT EFI_STRING *Results\r
696 )\r
697{\r
93e3992d 698 EFI_STATUS Status;\r
93e3992d 699 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
8d00a0f1 700 EFI_STRING AccessResults; \r
701 UINTN Index;\r
702 EFI_HANDLE *ConfigAccessHandles;\r
703 UINTN NumberConfigAccessHandles;\r
704 BOOLEAN FirstElement;\r
93e3992d 705\r
706 if (This == NULL || Results == NULL) {\r
707 return EFI_INVALID_PARAMETER;\r
708 }\r
709\r
93e3992d 710 //\r
711 // Allocate a fix length of memory to store Results. Reallocate memory for\r
712 // Results if this fix length is insufficient.\r
713 //\r
714 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
715 if (*Results == NULL) {\r
716 return EFI_OUT_OF_RESOURCES;\r
717 }\r
718\r
8d00a0f1 719 NumberConfigAccessHandles = 0;\r
720 Status = gBS->LocateHandleBuffer (\r
721 ByProtocol,\r
722 &gEfiHiiConfigAccessProtocolGuid,\r
723 NULL,\r
724 &NumberConfigAccessHandles,\r
725 &ConfigAccessHandles\r
726 );\r
727 if (EFI_ERROR (Status)) {\r
728 return Status;\r
729 }\r
93e3992d 730\r
8d00a0f1 731 FirstElement = TRUE;\r
93e3992d 732\r
8d00a0f1 733 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
93e3992d 734 Status = gBS->HandleProtocol (\r
8d00a0f1 735 ConfigAccessHandles[Index],\r
93e3992d 736 &gEfiHiiConfigAccessProtocolGuid,\r
8d00a0f1 737 (VOID **) &ConfigAccess\r
93e3992d 738 );\r
8d00a0f1 739 if (EFI_ERROR (Status)) {\r
740 continue;\r
741 }\r
93e3992d 742\r
743 Status = ConfigAccess->ExtractConfig (\r
744 ConfigAccess,\r
8d00a0f1 745 NULL,\r
746 NULL,\r
93e3992d 747 &AccessResults\r
748 );\r
8d00a0f1 749 if (!EFI_ERROR (Status)) {\r
750 //\r
751 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
752 // which seperates the first <ConfigAltResp> and the following ones. \r
753 //\r
754 if (!FirstElement) {\r
755 Status = AppendToMultiString (Results, L"&");\r
756 ASSERT_EFI_ERROR (Status);\r
676df92c 757 }\r
8d00a0f1 758 \r
759 Status = AppendToMultiString (Results, AccessResults);\r
760 ASSERT_EFI_ERROR (Status);\r
93e3992d 761\r
8d00a0f1 762 FirstElement = FALSE;\r
763 \r
764 FreePool (AccessResults);\r
765 AccessResults = NULL;\r
766 }\r
93e3992d 767 }\r
f4113e1f 768 FreePool (ConfigAccessHandles);\r
93e3992d 769\r
8d00a0f1 770 return EFI_SUCCESS; \r
93e3992d 771}\r
772\r
773\r
774/**\r
775 This function processes the results of processing forms and routes it to the\r
776 appropriate handlers or storage.\r
777\r
778 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
779 instance.\r
780 @param Configuration A null-terminated Unicode string in\r
781 <MulltiConfigResp> format.\r
782 @param Progress A pointer to a string filled in with the offset of\r
783 the most recent & before the first failing name /\r
784 value pair (or the beginning of the string if the\r
785 failure is in the first name / value pair) or the\r
786 terminating NULL if all was successful.\r
787\r
788 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
789 distribution.\r
790 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
791 results that must be stored awaiting possible\r
792 future protocols.\r
793 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
794 would result in this type of error.\r
795 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
796 found.\r
797\r
798**/\r
799EFI_STATUS\r
800EFIAPI\r
813acf3a 801HiiConfigRoutingRouteConfig (\r
93e3992d 802 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
803 IN CONST EFI_STRING Configuration,\r
804 OUT EFI_STRING *Progress\r
805 )\r
806{\r
93e3992d 807 EFI_STRING StringPtr;\r
808 EFI_STRING ConfigResp;\r
809 UINTN Length;\r
810 EFI_STATUS Status;\r
811 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
326c6b71 812 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
93e3992d 813 EFI_HANDLE DriverHandle;\r
814 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
815 EFI_STRING AccessProgress;\r
93e3992d 816\r
817 if (This == NULL || Progress == NULL) {\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 if (Configuration == NULL) {\r
822 *Progress = NULL;\r
823 return EFI_INVALID_PARAMETER;\r
824 }\r
825\r
93e3992d 826 StringPtr = Configuration;\r
827 *Progress = StringPtr;\r
828\r
829 //\r
830 // The first element of <MultiConfigResp> should be\r
831 // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
832 //\r
833 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
834 return EFI_INVALID_PARAMETER;\r
835 }\r
836\r
837 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
838 //\r
839 // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
840 // or most recent & before the error.\r
841 //\r
842 if (StringPtr == Configuration) {\r
843 *Progress = StringPtr;\r
844 } else {\r
845 *Progress = StringPtr - 1;\r
846 }\r
847\r
848 //\r
849 // Process each <ConfigResp> of <MultiConfigResp>\r
850 //\r
851 Length = CalculateConfigStringLen (StringPtr);\r
852 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
853 if (ConfigResp == NULL) {\r
854 return EFI_OUT_OF_RESOURCES;\r
855 }\r
856 //\r
857 // Append '\0' to the end of ConfigRequest\r
858 //\r
859 *(ConfigResp + Length) = 0;\r
860\r
861 //\r
862 // Get the UEFI device path\r
863 //\r
864 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
865 if (EFI_ERROR (Status)) {\r
676df92c 866 FreePool (ConfigResp);\r
93e3992d 867 return Status;\r
868 }\r
869\r
870 //\r
326c6b71 871 // Find driver handle by device path\r
93e3992d 872 //\r
873 DriverHandle = NULL;\r
326c6b71 874 TempDevicePath = DevicePath;\r
875 Status = gBS->LocateDevicePath (\r
876 &gEfiDevicePathProtocolGuid,\r
877 &TempDevicePath,\r
878 &DriverHandle\r
879 );\r
676df92c 880 FreePool (DevicePath);\r
93e3992d 881\r
326c6b71 882 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
93e3992d 883 //\r
326c6b71 884 // Cannot find any known driver.\r
93e3992d 885 // Set Progress to the 'G' in "GUID" of the routing header.\r
886 //\r
887 *Progress = StringPtr;\r
676df92c 888 FreePool (ConfigResp);\r
93e3992d 889 return EFI_NOT_FOUND;\r
890 }\r
891\r
892 //\r
893 // Call corresponding ConfigAccess protocol to route settings\r
894 //\r
895 Status = gBS->HandleProtocol (\r
896 DriverHandle,\r
897 &gEfiHiiConfigAccessProtocolGuid,\r
898 (VOID **) &ConfigAccess\r
899 );\r
900 ASSERT_EFI_ERROR (Status);\r
901\r
902 Status = ConfigAccess->RouteConfig (\r
903 ConfigAccess,\r
904 ConfigResp,\r
905 &AccessProgress\r
906 );\r
907\r
908 if (EFI_ERROR (Status)) {\r
909 //\r
910 // AccessProgress indicates the parsing progress on <ConfigResp>.\r
911 // Map it to the progress on <MultiConfigResp> then return it.\r
912 //\r
8d00a0f1 913 *Progress = StrStr (StringPtr, AccessProgress);\r
93e3992d 914\r
676df92c 915 FreePool (ConfigResp);\r
93e3992d 916 return Status;\r
917 }\r
918\r
676df92c 919 FreePool (ConfigResp);\r
93e3992d 920 ConfigResp = NULL;\r
921\r
922 //\r
923 // Go to next <ConfigResp> (skip '&').\r
924 //\r
925 StringPtr += Length;\r
926 if (*StringPtr == 0) {\r
927 *Progress = StringPtr;\r
928 break;\r
929 }\r
930\r
931 StringPtr++;\r
932\r
933 }\r
934\r
935 return EFI_SUCCESS;\r
93e3992d 936}\r
937\r
938\r
939/**\r
940 This helper function is to be called by drivers to map configuration data\r
941 stored in byte array ("block") formats such as UEFI Variables into current\r
942 configuration strings.\r
943\r
944 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
945 instance.\r
946 @param ConfigRequest A null-terminated Unicode string in\r
947 <ConfigRequest> format.\r
948 @param Block Array of bytes defining the block's configuration.\r
949 @param BlockSize Length in bytes of Block.\r
950 @param Config Filled-in configuration string. String allocated\r
951 by the function. Returned only if call is\r
952 successful.\r
953 @param Progress A pointer to a string filled in with the offset of\r
954 the most recent & before the first failing\r
955 name/value pair (or the beginning of the string if\r
956 the failure is in the first name / value pair) or\r
957 the terminating NULL if all was successful.\r
958\r
959 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
960 terminator at the end of the ConfigRequest\r
961 string.\r
962 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
963 points to the first character of ConfigRequest.\r
964 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
965 Block parameter would result in this type of\r
966 error. Progress points to the first character of\r
967 ConfigRequest.\r
968 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
969 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
970 Block is left updated and Progress points at\r
971 the "&" preceding the first non-<BlockName>.\r
972\r
973**/\r
974EFI_STATUS\r
975EFIAPI\r
976HiiBlockToConfig (\r
977 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
978 IN CONST EFI_STRING ConfigRequest,\r
979 IN CONST UINT8 *Block,\r
980 IN CONST UINTN BlockSize,\r
981 OUT EFI_STRING *Config,\r
982 OUT EFI_STRING *Progress\r
983 )\r
984{\r
93e3992d 985 EFI_STRING StringPtr;\r
986 UINTN Length;\r
987 EFI_STATUS Status;\r
988 EFI_STRING TmpPtr;\r
989 UINT8 *TmpBuffer;\r
990 UINTN Offset;\r
991 UINTN Width;\r
992 UINT8 *Value;\r
993 EFI_STRING ValueStr;\r
994 EFI_STRING ConfigElement;\r
63d55bb9
LG
995 UINTN Index;\r
996 UINT8 *TemBuffer;\r
997 CHAR16 *TemString;\r
93e3992d 998\r
999 if (This == NULL || Progress == NULL || Config == NULL) {\r
1000 return EFI_INVALID_PARAMETER;\r
1001 }\r
1002\r
1003 if (Block == NULL || ConfigRequest == NULL) {\r
1004 *Progress = ConfigRequest;\r
1005 return EFI_INVALID_PARAMETER;\r
1006 }\r
1007\r
93e3992d 1008 StringPtr = ConfigRequest;\r
1009 ValueStr = NULL;\r
1010 Value = NULL;\r
1011 ConfigElement = NULL;\r
1012\r
1013 //\r
1014 // Allocate a fix length of memory to store Results. Reallocate memory for\r
1015 // Results if this fix length is insufficient.\r
1016 //\r
1017 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
1018 if (*Config == NULL) {\r
1019 return EFI_OUT_OF_RESOURCES;\r
1020 }\r
1021\r
1022 //\r
1023 // Jump <ConfigHdr>\r
1024 //\r
1025 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1026 *Progress = StringPtr;\r
1027 Status = EFI_INVALID_PARAMETER;\r
1028 goto Exit;\r
1029 }\r
1030 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1031 StringPtr++;\r
1032 }\r
1033 if (*StringPtr == 0) {\r
1034 *Progress = StringPtr;\r
1035 Status = EFI_INVALID_PARAMETER;\r
1036 goto Exit;\r
1037 }\r
08e6463a 1038\r
1039 while (*StringPtr != L'&' && *StringPtr != 0) {\r
1040 StringPtr++;\r
1041 }\r
1042 if (*StringPtr == 0) {\r
1043 *Progress = StringPtr;\r
1044 Status = EFI_INVALID_PARAMETER;\r
1045 goto Exit;\r
1046 }\r
1047 //\r
1048 // Skip '&'\r
1049 //\r
1050 StringPtr++;\r
93e3992d 1051\r
1052 //\r
1053 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
1054 //\r
1055 Length = StringPtr - ConfigRequest;\r
1056 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
1057\r
1058 //\r
1059 // Parse each <RequestElement> if exists\r
1060 // Only <BlockName> format is supported by this help function.\r
1061 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
1062 //\r
1063 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1064 //\r
1065 // Back up the header of one <BlockName>\r
1066 //\r
1067 TmpPtr = StringPtr;\r
1068\r
1069 StringPtr += StrLen (L"OFFSET=");\r
1070 //\r
1071 // Get Offset\r
1072 //\r
1073 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1074 if (Status == EFI_OUT_OF_RESOURCES) {\r
1075 *Progress = ConfigRequest;\r
1076 goto Exit;\r
1077 }\r
1078 Offset = 0;\r
1079 CopyMem (\r
1080 &Offset,\r
1081 TmpBuffer,\r
1082 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1083 );\r
676df92c 1084 FreePool (TmpBuffer);\r
93e3992d 1085\r
1086 StringPtr += Length;\r
1087 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1088 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1089 Status = EFI_INVALID_PARAMETER;\r
1090 goto Exit;\r
1091 }\r
1092 StringPtr += StrLen (L"&WIDTH=");\r
1093\r
1094 //\r
1095 // Get Width\r
1096 //\r
1097 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1098 if (Status == EFI_OUT_OF_RESOURCES) {\r
1099 *Progress = ConfigRequest;\r
1100 goto Exit;\r
1101 }\r
1102 Width = 0;\r
1103 CopyMem (\r
1104 &Width,\r
1105 TmpBuffer,\r
1106 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1107 );\r
676df92c 1108 FreePool (TmpBuffer);\r
93e3992d 1109\r
1110 StringPtr += Length;\r
1111 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1112 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1113 Status = EFI_INVALID_PARAMETER;\r
1114 goto Exit;\r
1115 }\r
1116\r
1117 //\r
1118 // Calculate Value and convert it to hex string.\r
1119 //\r
1120 if (Offset + Width > BlockSize) {\r
1121 *Progress = StringPtr;\r
1122 Status = EFI_DEVICE_ERROR;\r
1123 goto Exit;\r
1124 }\r
1125\r
1126 Value = (UINT8 *) AllocateZeroPool (Width);\r
1127 if (Value == NULL) {\r
1128 *Progress = ConfigRequest;\r
1129 Status = EFI_OUT_OF_RESOURCES;\r
1130 goto Exit;\r
1131 }\r
1132\r
1133 CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
1134\r
1135 Length = Width * 2 + 1;\r
1136 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1137 if (ValueStr == NULL) {\r
1138 *Progress = ConfigRequest;\r
1139 Status = EFI_OUT_OF_RESOURCES;\r
1140 goto Exit;\r
1141 }\r
63d55bb9
LG
1142 \r
1143 TemString = ValueStr;\r
1144 TemBuffer = Value + Width - 1;\r
1145 for (Index = 0; Index < Width; Index ++, TemBuffer --) {\r
1146 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1147 }\r
1148 HiiToLower (ValueStr);\r
813acf3a 1149\r
676df92c 1150 FreePool (Value);\r
93e3992d 1151 Value = NULL;\r
1152\r
1153 //\r
1154 // Build a ConfigElement\r
1155 //\r
1156 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
1157 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
1158 if (ConfigElement == NULL) {\r
1159 Status = EFI_OUT_OF_RESOURCES;\r
1160 goto Exit;\r
1161 }\r
1162 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
1163 if (*StringPtr == 0) {\r
1164 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
1165 }\r
1166 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
1167 StrCat (ConfigElement, L"VALUE=");\r
1168 StrCat (ConfigElement, ValueStr);\r
1169\r
1170 AppendToMultiString (Config, ConfigElement);\r
1171\r
676df92c 1172 FreePool (ConfigElement);\r
1173 FreePool (ValueStr);\r
93e3992d 1174 ConfigElement = NULL;\r
1175 ValueStr = NULL;\r
1176\r
1177 //\r
1178 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1179 //\r
1180 if (*StringPtr == 0) {\r
1181 break;\r
1182 }\r
1183 AppendToMultiString (Config, L"&");\r
1184 StringPtr++;\r
1185\r
1186 }\r
1187\r
1188 if (*StringPtr != 0) {\r
1189 *Progress = StringPtr - 1;\r
1190 Status = EFI_INVALID_PARAMETER;\r
1191 goto Exit;\r
1192 }\r
1193\r
1194 *Progress = StringPtr;\r
1195 return EFI_SUCCESS;\r
1196\r
1197Exit:\r
676df92c 1198 FreePool (*Config);\r
1199 if (ValueStr != NULL) {\r
1200 FreePool (ValueStr);\r
1201 }\r
1202 if (Value != NULL) {\r
1203 FreePool (Value);\r
1204 }\r
69367b5b 1205 if (ConfigElement != NULL) {\r
676df92c 1206 FreePool (ConfigElement);\r
1207 }\r
93e3992d 1208\r
1209 return Status;\r
1210\r
1211}\r
1212\r
1213\r
1214/**\r
1215 This helper function is to be called by drivers to map configuration strings\r
1216 to configurations stored in byte array ("block") formats such as UEFI Variables.\r
1217\r
1218 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1219 instance.\r
1220 @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
1221 format.\r
1222 @param Block A possibly null array of bytes representing the\r
1223 current block. Only bytes referenced in the\r
1224 ConfigResp string in the block are modified. If\r
1225 this parameter is null or if the *BlockSize\r
1226 parameter is (on input) shorter than required by\r
1227 the Configuration string, only the BlockSize\r
1228 parameter is updated and an appropriate status\r
1229 (see below) is returned.\r
1230 @param BlockSize The length of the Block in units of UINT8. On\r
1231 input, this is the size of the Block. On output,\r
1232 if successful, contains the index of the last\r
1233 modified byte in the Block.\r
1234 @param Progress On return, points to an element of the ConfigResp\r
1235 string filled in with the offset of the most\r
1236 recent '&' before the first failing name / value\r
1237 pair (or the beginning of the string if the\r
1238 failure is in the first name / value pair) or the\r
1239 terminating NULL if all was successful.\r
1240\r
1241 @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
1242 terminator at the end of the ConfigResp string.\r
1243 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
1244 points to the first character of ConfigResp.\r
1245 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
1246 Block parameter would result in this type of\r
1247 error. Progress points to the first character of\r
1248 ConfigResp.\r
1249 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
1250 value pair. Block is left updated and\r
1251 Progress points at the '&' preceding the first\r
1252 non-<BlockName>.\r
1253\r
1254**/\r
1255EFI_STATUS\r
1256EFIAPI\r
1257HiiConfigToBlock (\r
1258 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1259 IN CONST EFI_STRING ConfigResp,\r
1260 IN OUT UINT8 *Block,\r
1261 IN OUT UINTN *BlockSize,\r
1262 OUT EFI_STRING *Progress\r
1263 )\r
1264{\r
1265 HII_DATABASE_PRIVATE_DATA *Private;\r
1266 EFI_STRING StringPtr;\r
1267 UINTN Length;\r
1268 EFI_STATUS Status;\r
1269 UINT8 *TmpBuffer;\r
1270 UINTN Offset;\r
1271 UINTN Width;\r
1272 UINT8 *Value;\r
1273 UINTN BufferSize;\r
1274\r
1275 if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
1276 return EFI_INVALID_PARAMETER;\r
1277 }\r
1278\r
1279 if (ConfigResp == NULL || Block == NULL) {\r
1280 *Progress = ConfigResp;\r
1281 return EFI_INVALID_PARAMETER;\r
1282 }\r
1283\r
1284 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1285 ASSERT (Private != NULL);\r
1286\r
1287 StringPtr = ConfigResp;\r
1288 BufferSize = *BlockSize;\r
1289 Value = NULL;\r
1290\r
1291 //\r
1292 // Jump <ConfigHdr>\r
1293 //\r
1294 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1295 *Progress = StringPtr;\r
1296 Status = EFI_INVALID_PARAMETER;\r
1297 goto Exit;\r
1298 }\r
1299 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
1300 StringPtr++;\r
1301 }\r
1302 if (*StringPtr == 0) {\r
1303 *Progress = StringPtr;\r
1304 Status = EFI_INVALID_PARAMETER;\r
1305 goto Exit;\r
1306 }\r
08e6463a 1307\r
1308 while (*StringPtr != L'&' && *StringPtr != 0) {\r
1309 StringPtr++;\r
1310 }\r
1311 if (*StringPtr == 0) {\r
1312 *Progress = StringPtr;\r
1313 Status = EFI_INVALID_PARAMETER;\r
1314 goto Exit;\r
1315 }\r
1316 //\r
1317 // Skip '&'\r
1318 //\r
1319 StringPtr++;\r
93e3992d 1320\r
1321 //\r
1322 // Parse each <ConfigElement> if exists\r
1323 // Only <BlockConfig> format is supported by this help function.\r
1324 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
1325 //\r
1326 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
1327 StringPtr += StrLen (L"OFFSET=");\r
1328 //\r
1329 // Get Offset\r
1330 //\r
1331 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
7c1bc8d6 1332 if (EFI_ERROR (Status)) {\r
93e3992d 1333 *Progress = ConfigResp;\r
1334 goto Exit;\r
1335 }\r
1336 Offset = 0;\r
1337 CopyMem (\r
1338 &Offset,\r
1339 TmpBuffer,\r
1340 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1341 );\r
676df92c 1342 FreePool (TmpBuffer);\r
93e3992d 1343\r
1344 StringPtr += Length;\r
1345 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1346 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
1347 Status = EFI_INVALID_PARAMETER;\r
1348 goto Exit;\r
1349 }\r
1350 StringPtr += StrLen (L"&WIDTH=");\r
1351\r
1352 //\r
1353 // Get Width\r
1354 //\r
1355 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1356 if (Status == EFI_OUT_OF_RESOURCES) {\r
1357 *Progress = ConfigResp;\r
1358 goto Exit;\r
1359 }\r
1360 Width = 0;\r
1361 CopyMem (\r
1362 &Width,\r
1363 TmpBuffer,\r
1364 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
1365 );\r
676df92c 1366 FreePool (TmpBuffer);\r
93e3992d 1367\r
1368 StringPtr += Length;\r
1369 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
1370 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
1371 Status = EFI_INVALID_PARAMETER;\r
1372 goto Exit;\r
1373 }\r
1374 StringPtr += StrLen (L"&VALUE=");\r
1375\r
1376 //\r
1377 // Get Value\r
1378 //\r
1379 Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
7c1bc8d6 1380 if (EFI_ERROR (Status)) {\r
93e3992d 1381 *Progress = ConfigResp;\r
1382 goto Exit;\r
1383 }\r
1384\r
1385 StringPtr += Length;\r
1386 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1387 *Progress = StringPtr - Length - 7;\r
1388 Status = EFI_INVALID_PARAMETER;\r
1389 goto Exit;\r
1390 }\r
1391\r
1392 //\r
1393 // Update the Block with configuration info\r
1394 //\r
1395\r
1396 if (Offset + Width > BufferSize) {\r
1397 return EFI_DEVICE_ERROR;\r
1398 }\r
1399\r
1400 CopyMem (Block + Offset, Value, Width);\r
1401 *BlockSize = Offset + Width - 1;\r
1402\r
676df92c 1403 FreePool (Value);\r
93e3992d 1404 Value = NULL;\r
1405\r
1406 //\r
1407 // If '\0', parsing is finished. Otherwise skip '&' to continue\r
1408 //\r
1409 if (*StringPtr == 0) {\r
1410 break;\r
1411 }\r
1412\r
1413 StringPtr++;\r
1414 }\r
1415\r
1416 if (*StringPtr != 0) {\r
1417 *Progress = StringPtr - 1;\r
1418 Status = EFI_INVALID_PARAMETER;\r
1419 goto Exit;\r
1420 }\r
1421\r
1422 *Progress = StringPtr;\r
1423 return EFI_SUCCESS;\r
1424\r
1425Exit:\r
1426\r
676df92c 1427 if (Value != NULL) {\r
1428 FreePool (Value);\r
1429 }\r
93e3992d 1430 return Status;\r
1431}\r
1432\r
1433\r
1434/**\r
1435 This helper function is to be called by drivers to extract portions of\r
1436 a larger configuration string.\r
1437\r
1438 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
1439 instance.\r
1440 @param Configuration A null-terminated Unicode string in\r
1441 <MultiConfigAltResp> format.\r
1442 @param Guid A pointer to the GUID value to search for in the\r
1443 routing portion of the ConfigResp string when\r
1444 retrieving the requested data. If Guid is NULL,\r
1445 then all GUID values will be searched for.\r
1446 @param Name A pointer to the NAME value to search for in the\r
1447 routing portion of the ConfigResp string when\r
1448 retrieving the requested data. If Name is NULL,\r
1449 then all Name values will be searched for.\r
1450 @param DevicePath A pointer to the PATH value to search for in the\r
1451 routing portion of the ConfigResp string when\r
1452 retrieving the requested data. If DevicePath is\r
1453 NULL, then all DevicePath values will be searched\r
1454 for.\r
1455 @param AltCfgId A pointer to the ALTCFG value to search for in the\r
1456 routing portion of the ConfigResp string when\r
1457 retrieving the requested data. If this parameter\r
1458 is NULL, then the current setting will be\r
1459 retrieved.\r
1460 @param AltCfgResp A pointer to a buffer which will be allocated by\r
1461 the function which contains the retrieved string\r
1462 as requested. This buffer is only allocated if\r
1463 the call was successful.\r
1464\r
1465 @retval EFI_SUCCESS The request succeeded. The requested data was\r
1466 extracted and placed in the newly allocated\r
1467 AltCfgResp buffer.\r
1468 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
1469 @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
1470 @retval EFI_NOT_FOUND Target for the specified routing data was not\r
1471 found.\r
1472\r
1473**/\r
1474EFI_STATUS\r
1475EFIAPI\r
1476HiiGetAltCfg (\r
1477 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
1478 IN CONST EFI_STRING Configuration,\r
1479 IN CONST EFI_GUID *Guid,\r
1480 IN CONST EFI_STRING Name,\r
1481 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1482 IN CONST UINT16 *AltCfgId,\r
1483 OUT EFI_STRING *AltCfgResp\r
1484 )\r
1485{\r
93e3992d 1486 EFI_STATUS Status;\r
1487 EFI_STRING StringPtr;\r
e90b081a 1488 EFI_STRING HdrStart;\r
1489 EFI_STRING HdrEnd;\r
93e3992d 1490 EFI_STRING TmpPtr;\r
1491 UINTN Length;\r
e90b081a 1492 EFI_STRING GuidStr;\r
1493 EFI_STRING NameStr;\r
1494 EFI_STRING PathStr;\r
1495 EFI_STRING AltIdStr;\r
1496 EFI_STRING Result;\r
1497 BOOLEAN GuidFlag;\r
1498 BOOLEAN NameFlag;\r
1499 BOOLEAN PathFlag;\r
1500\r
1501 HdrStart = NULL;\r
1502 HdrEnd = NULL;\r
1503 GuidStr = NULL;\r
1504 NameStr = NULL;\r
1505 PathStr = NULL;\r
1506 AltIdStr = NULL;\r
1507 Result = NULL;\r
1508 GuidFlag = FALSE;\r
1509 NameFlag = FALSE;\r
1510 PathFlag = FALSE;\r
93e3992d 1511\r
1512 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
1513 return EFI_INVALID_PARAMETER;\r
1514 }\r
1515\r
1516 StringPtr = Configuration;\r
1517 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1518 return EFI_INVALID_PARAMETER;\r
1519 }\r
1520\r
1521 //\r
1522 // Generate the sub string for later matching.\r
1523 //\r
813acf3a 1524 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
93e3992d 1525 GenerateSubStr (\r
1526 L"PATH=",\r
1527 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
813acf3a 1528 (VOID *) DevicePath,\r
1529 1,\r
93e3992d 1530 &PathStr\r
1531 );\r
1532 if (AltCfgId != NULL) {\r
813acf3a 1533 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
93e3992d 1534 }\r
1535 if (Name != NULL) {\r
813acf3a 1536 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
93e3992d 1537 } else {\r
813acf3a 1538 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
93e3992d 1539 }\r
1540\r
1541 while (*StringPtr != 0) {\r
1542 //\r
1543 // Try to match the GUID\r
1544 //\r
1545 if (!GuidFlag) {\r
1546 TmpPtr = StrStr (StringPtr, GuidStr);\r
1547 if (TmpPtr == NULL) {\r
1548 Status = EFI_NOT_FOUND;\r
1549 goto Exit;\r
1550 }\r
1551 HdrStart = TmpPtr;\r
1552\r
1553 //\r
1554 // Jump to <NameHdr>\r
1555 //\r
1556 if (Guid != NULL) {\r
1557 StringPtr = TmpPtr + StrLen (GuidStr);\r
1558 } else {\r
1559 StringPtr = StrStr (TmpPtr, L"NAME=");\r
1560 if (StringPtr == NULL) {\r
1561 Status = EFI_NOT_FOUND;\r
1562 goto Exit;\r
1563 }\r
1564 }\r
1565 GuidFlag = TRUE;\r
1566 }\r
1567\r
1568 //\r
1569 // Try to match the NAME\r
1570 //\r
1571 if (GuidFlag && !NameFlag) {\r
1572 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
1573 GuidFlag = FALSE;\r
1574 } else {\r
1575 //\r
1576 // Jump to <PathHdr>\r
1577 //\r
1578 if (Name != NULL) {\r
1579 StringPtr += StrLen (NameStr);\r
1580 } else {\r
1581 StringPtr = StrStr (StringPtr, L"PATH=");\r
1582 if (StringPtr == NULL) {\r
1583 Status = EFI_NOT_FOUND;\r
1584 goto Exit;\r
1585 }\r
1586 }\r
1587 NameFlag = TRUE;\r
1588 }\r
1589 }\r
1590\r
1591 //\r
1592 // Try to match the DevicePath\r
1593 //\r
1594 if (GuidFlag && NameFlag && !PathFlag) {\r
1595 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
1596 GuidFlag = FALSE;\r
1597 NameFlag = FALSE;\r
1598 } else {\r
1599 //\r
1600 // Jump to '&' before <DescHdr> or <ConfigBody>\r
1601 //\r
1602 if (DevicePath != NULL) {\r
1603 StringPtr += StrLen (PathStr);\r
1604 } else {\r
1605 StringPtr = StrStr (StringPtr, L"&");\r
1606 if (StringPtr == NULL) {\r
1607 Status = EFI_NOT_FOUND;\r
1608 goto Exit;\r
1609 }\r
1610 }\r
1611 PathFlag = TRUE;\r
1612 HdrEnd = ++StringPtr;\r
1613 }\r
1614 }\r
1615\r
1616 //\r
1617 // Try to match the AltCfgId\r
1618 //\r
1619 if (GuidFlag && NameFlag && PathFlag) {\r
1620 if (AltCfgId == NULL) {\r
1621 //\r
1622 // Return Current Setting when AltCfgId is NULL.\r
1623 //\r
1624 Status = OutputConfigBody (StringPtr, &Result);\r
1625 goto Exit;\r
1626 }\r
1627 //\r
1628 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
1629 //\r
1630 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
1631 GuidFlag = FALSE;\r
1632 NameFlag = FALSE;\r
1633 PathFlag = FALSE;\r
1634 } else {\r
1635 Status = OutputConfigBody (StringPtr, &Result);\r
1636 goto Exit;\r
1637 }\r
1638 }\r
1639 }\r
1640\r
1641 Status = EFI_NOT_FOUND;\r
1642\r
1643Exit:\r
1644\r
bc166db3 1645 if (!EFI_ERROR (Status) && (Result != NULL)) {\r
93e3992d 1646 //\r
1647 // Copy the <ConfigHdr> and <ConfigBody>\r
1648 //\r
1649 Length = HdrEnd - HdrStart + StrLen (Result);\r
1650 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
1651 if (*AltCfgResp == NULL) {\r
1652 Status = EFI_OUT_OF_RESOURCES;\r
1653 } else {\r
1654 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
1655 StrCat (*AltCfgResp, Result);\r
1656 Status = EFI_SUCCESS;\r
1657 }\r
1658 }\r
1659\r
676df92c 1660 if (GuidStr != NULL) {\r
1661 FreePool (GuidStr);\r
1662 }\r
1663 if (NameStr != NULL) {\r
1664 FreePool (NameStr);\r
1665 }\r
1666 if (PathStr != NULL) {\r
1667 FreePool (PathStr);\r
1668 }\r
1669 if (AltIdStr != NULL) {\r
1670 FreePool (AltIdStr);\r
1671 }\r
1672 if (Result != NULL) {\r
1673 FreePool (Result);\r
1674 }\r
93e3992d 1675\r
1676 return Status;\r
1677\r
93e3992d 1678}\r
1679\r
36fe40c2 1680\r