]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
MdeModulePkg: Replace [Ascii|Unicode]ValueToString
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigKeywordHandler.c
CommitLineData
87bfeb11
ED
1/** @file\r
2Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.\r
3\r
9f4048f7 4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
87bfeb11
ED
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15\r
16#include "HiiDatabase.h"\r
17\r
18extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
19\r
20/**\r
21 Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
22 from <PathHdr> of <MultiKeywordRequest>.\r
23\r
24 This is a internal function.\r
25\r
26 @param String MultiKeywordRequest string.\r
27 @param DevicePathData Binary of a UEFI device path.\r
28 @param NextString string follow the possible PathHdr string.\r
29\r
30 @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.\r
4a429716 31 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.\r
87bfeb11
ED
32 @retval EFI_SUCCESS The device path is retrieved and translated to binary format.\r
33 The Input string not include PathHdr section.\r
34\r
35**/\r
36EFI_STATUS\r
37ExtractDevicePath (\r
38 IN EFI_STRING String,\r
39 OUT UINT8 **DevicePathData,\r
40 OUT EFI_STRING *NextString\r
41 )\r
42{\r
43 UINTN Length;\r
44 EFI_STRING PathHdr;\r
45 UINT8 *DevicePathBuffer;\r
46 CHAR16 TemStr[2];\r
47 UINTN Index;\r
48 UINT8 DigitUint8;\r
49 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
50\r
51 ASSERT (NextString != NULL && DevicePathData != NULL);\r
52\r
53 //\r
54 // KeywordRequest == NULL case.\r
55 //\r
56 if (String == NULL) {\r
57 *DevicePathData = NULL;\r
58 *NextString = NULL;\r
59 return EFI_SUCCESS;\r
60 }\r
61\r
62 //\r
63 // Skip '&' if exist.\r
64 //\r
65 if (*String == L'&') {\r
66 String ++;\r
67 }\r
68\r
69 //\r
70 // Find the 'PATH=' of <PathHdr>.\r
71 //\r
72 if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {\r
73 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
74 return EFI_INVALID_PARAMETER;\r
75 } else {\r
76 //\r
77 // Not include PathHdr, return success and DevicePath = NULL.\r
78 //\r
79 *DevicePathData = NULL;\r
80 *NextString = String;\r
81 return EFI_SUCCESS;\r
82 }\r
83 }\r
84\r
85 //\r
86 // Check whether path data does exist.\r
87 //\r
88 String += StrLen (L"PATH=");\r
89 if (*String == 0) {\r
90 return EFI_INVALID_PARAMETER;\r
91 }\r
92 PathHdr = String;\r
93\r
94 //\r
95 // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
96 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
97 // of UEFI device path.\r
98 //\r
99 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
100\r
101 //\r
102 // Save the return next keyword string value.\r
103 //\r
104 *NextString = String;\r
105\r
106 //\r
107 // Check DevicePath Length\r
108 //\r
109 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112 \r
113 //\r
114 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
115 // as the device path resides in RAM memory.\r
116 // Translate the data into binary.\r
117 //\r
118 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
119 if (DevicePathBuffer == NULL) {\r
120 return EFI_OUT_OF_RESOURCES;\r
121 }\r
122 \r
123 //\r
124 // Convert DevicePath\r
125 //\r
126 ZeroMem (TemStr, sizeof (TemStr));\r
127 for (Index = 0; Index < Length; Index ++) {\r
128 TemStr[0] = PathHdr[Index];\r
129 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
130 if ((Index & 1) == 0) {\r
131 DevicePathBuffer [Index/2] = DigitUint8;\r
132 } else {\r
133 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
134 }\r
135 }\r
136 \r
137 //\r
138 // Validate DevicePath\r
139 //\r
140 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;\r
141 while (!IsDevicePathEnd (DevicePath)) {\r
142 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
143 //\r
144 // Invalid device path\r
145 //\r
146 FreePool (DevicePathBuffer);\r
147 return EFI_INVALID_PARAMETER;\r
148 }\r
149 DevicePath = NextDevicePathNode (DevicePath);\r
150 }\r
151\r
152 //\r
153 // return the device path\r
154 //\r
155 *DevicePathData = DevicePathBuffer;\r
156\r
157 return EFI_SUCCESS;\r
158}\r
159\r
160/**\r
161 Get NameSpace from the input NameSpaceId string.\r
162\r
163 This is a internal function.\r
164\r
165 @param String <NameSpaceId> format string.\r
166 @param NameSpace Return the name space string.\r
167 @param NextString Return the next string follow namespace.\r
168\r
169 @retval EFI_SUCCESS Get the namespace string success.\r
170 @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.\r
171\r
172**/\r
173EFI_STATUS\r
174ExtractNameSpace (\r
175 IN EFI_STRING String,\r
176 OUT CHAR8 **NameSpace,\r
177 OUT EFI_STRING *NextString\r
178 )\r
179{\r
180 CHAR16 *TmpPtr;\r
b68ccac1 181 UINTN NameSpaceSize;\r
87bfeb11
ED
182\r
183 ASSERT (NameSpace != NULL);\r
184\r
185 TmpPtr = NULL;\r
186\r
187 //\r
188 // Input NameSpaceId == NULL\r
189 //\r
190 if (String == NULL) {\r
191 *NameSpace = NULL;\r
192 if (NextString != NULL) {\r
193 *NextString = NULL;\r
194 }\r
195 return EFI_SUCCESS;\r
196 }\r
197\r
198 //\r
199 // Skip '&' if exist.\r
200 //\r
201 if (*String == L'&') {\r
202 String++;\r
203 }\r
204\r
205 if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {\r
206 return EFI_INVALID_PARAMETER;\r
207 }\r
208 String += StrLen (L"NAMESPACE=");\r
209\r
210 TmpPtr = StrStr (String, L"&");\r
211 if (TmpPtr != NULL) {\r
212 *TmpPtr = 0; \r
213 }\r
214 if (NextString != NULL) {\r
215 *NextString = String + StrLen (String);\r
216 }\r
217\r
218 //\r
219 // Input NameSpace is unicode string. The language in String package is ascii string.\r
220 // Here will convert the unicode string to ascii and save it.\r
221 //\r
b68ccac1
SZ
222 NameSpaceSize = StrLen (String) + 1;\r
223 *NameSpace = AllocatePool (NameSpaceSize);\r
87bfeb11
ED
224 if (*NameSpace == NULL) {\r
225 return EFI_OUT_OF_RESOURCES;\r
226 }\r
b68ccac1 227 UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);\r
87bfeb11
ED
228\r
229 if (TmpPtr != NULL) {\r
230 *TmpPtr = L'&'; \r
231 }\r
232\r
233 return EFI_SUCCESS;\r
234}\r
235\r
236/**\r
237 Get Keyword from the input KeywordRequest string.\r
238\r
239 This is a internal function.\r
240\r
241 @param String KeywordRequestformat string.\r
242 @param Keyword return the extract keyword string.\r
4a429716 243 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
244\r
245 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 246 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
247\r
248**/\r
249EFI_STATUS\r
250ExtractKeyword (\r
251 IN EFI_STRING String,\r
252 OUT EFI_STRING *Keyword,\r
253 OUT EFI_STRING *NextString\r
254 )\r
255{\r
256 EFI_STRING TmpPtr;\r
257\r
258 ASSERT ((Keyword != NULL) && (NextString != NULL));\r
259 \r
260 TmpPtr = NULL;\r
261\r
262 //\r
263 // KeywordRequest == NULL case.\r
264 //\r
265 if (String == NULL) {\r
266 *Keyword = NULL;\r
267 *NextString = NULL;\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
271 //\r
272 // Skip '&' if exist.\r
273 //\r
274 if (*String == L'&') {\r
275 String++;\r
276 }\r
277\r
278 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
279 return EFI_INVALID_PARAMETER;\r
280 }\r
281\r
282 String += StrLen (L"KEYWORD=");\r
283 \r
284 TmpPtr = StrStr (String, L"&");\r
285 if (TmpPtr != NULL) {\r
286 *TmpPtr = 0; \r
287 }\r
288 *NextString = String + StrLen (String);\r
289\r
290 *Keyword = AllocateCopyPool (StrSize (String), String);\r
291 if (*Keyword == NULL) {\r
292 return EFI_OUT_OF_RESOURCES;\r
293 }\r
294\r
295 if (TmpPtr != NULL) {\r
296 *TmpPtr = L'&';\r
297 }\r
298 \r
299 return EFI_SUCCESS;\r
300}\r
301\r
302/**\r
303 Get value from the input KeywordRequest string.\r
304\r
305 This is a internal function.\r
306\r
307 @param String KeywordRequestformat string.\r
308 @param Value return the extract value string.\r
4a429716 309 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
310\r
311 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 312 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
313\r
314**/\r
315EFI_STATUS\r
316ExtractValue (\r
317 IN EFI_STRING String,\r
318 OUT EFI_STRING *Value,\r
319 OUT EFI_STRING *NextString\r
320 )\r
321{\r
322 EFI_STRING TmpPtr;\r
323\r
324 ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));\r
325\r
326 //\r
327 // Skip '&' if exist.\r
328 //\r
329 if (*String == L'&') {\r
330 String++;\r
331 }\r
332\r
333 if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {\r
334 return EFI_INVALID_PARAMETER;\r
335 }\r
336\r
337 String += StrLen (L"VALUE=");\r
338 \r
339 TmpPtr = StrStr (String, L"&");\r
340 if (TmpPtr != NULL) {\r
341 *TmpPtr = 0; \r
342 }\r
343 *NextString = String + StrLen (String);\r
344\r
345 *Value = AllocateCopyPool (StrSize (String), String);\r
346 if (*Value == NULL) {\r
347 return EFI_OUT_OF_RESOURCES;\r
348 }\r
349\r
350 if (TmpPtr != NULL) {\r
351 *TmpPtr = L'&';\r
352 }\r
353 \r
354 return EFI_SUCCESS;\r
355}\r
356\r
357/**\r
358 Get filter from the input KeywordRequest string.\r
359\r
360 This is a internal function.\r
361\r
362 @param String KeywordRequestformat string.\r
363 @param FilterFlags return the filter condition.\r
4a429716 364 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
365\r
366 @retval EFI_SUCCESS Success to get the keyword string.\r
4a429716 367 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
87bfeb11
ED
368\r
369**/\r
370BOOLEAN\r
371ExtractFilter (\r
372 IN EFI_STRING String,\r
373 OUT UINT8 *FilterFlags,\r
374 OUT EFI_STRING *NextString\r
375 )\r
376{\r
377 CHAR16 *PathPtr;\r
378 CHAR16 *KeywordPtr;\r
379 BOOLEAN RetVal; \r
380\r
381 ASSERT ((FilterFlags != NULL) && (NextString != NULL));\r
382\r
383 //\r
384 // String end, no filter section.\r
385 //\r
386 if (String == NULL) {\r
387 *NextString = NULL;\r
388 return FALSE;\r
389 }\r
390 \r
391 *FilterFlags = 0;\r
392 RetVal = TRUE;\r
393\r
394 //\r
395 // Skip '&' if exist.\r
396 //\r
397 if (*String == L'&') {\r
398 String++;\r
399 }\r
400\r
401 if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {\r
402 //\r
403 // Find ReadOnly filter.\r
404 //\r
405 *FilterFlags |= EFI_KEYWORD_FILTER_READONY;\r
406 String += StrLen (L"ReadOnly");\r
407 } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {\r
408 //\r
409 // Find ReadWrite filter.\r
410 //\r
411 *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;\r
412 String += StrLen (L"ReadWrite");\r
413 } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {\r
414 //\r
415 // Find Buffer Filter.\r
416 //\r
417 *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;\r
418 String += StrLen (L"Buffer");\r
419 } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {\r
420 //\r
421 // Find Numeric Filter\r
422 //\r
423 String += StrLen (L"Numeric");\r
424 if (*String != L':') {\r
425 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;\r
426 } else {\r
427 String++;\r
428 switch (*String) {\r
429 case L'1':\r
430 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;\r
431 break;\r
432 case L'2':\r
433 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;\r
434 break;\r
435 case L'4':\r
436 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;\r
437 break;\r
438 case L'8':\r
439 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;\r
440 break;\r
441 default:\r
442 ASSERT (FALSE);\r
443 break;\r
444 }\r
445 String++;\r
446 }\r
447 } else {\r
448 //\r
449 // Check whether other filter item defined by Platform.\r
450 //\r
451 if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||\r
452 (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0)) {\r
453 //\r
454 // New KeywordRequest start, no platform defined filter.\r
455 //\r
456 } else {\r
457 //\r
458 // Platform defined filter rule.\r
459 // Just skip platform defined filter rule, return success.\r
460 //\r
461 PathPtr = StrStr(String, L"&PATH");\r
462 KeywordPtr = StrStr(String, L"&KEYWORD");\r
463 if (PathPtr != NULL && KeywordPtr != NULL) {\r
464 //\r
465 // If both sections exist, return the first follow string.\r
466 //\r
467 String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;\r
468 } else if (PathPtr != NULL) {\r
469 //\r
470 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.\r
471 //\r
472 ASSERT (FALSE);\r
473 } else if (KeywordPtr != NULL) {\r
474 //\r
475 // Just to the next keyword section.\r
476 //\r
477 String = KeywordPtr;\r
478 } else {\r
479 //\r
4a429716 480 // Only has platform defined filter section, just skip it.\r
87bfeb11
ED
481 //\r
482 String += StrLen (String);\r
483 }\r
484 }\r
485 RetVal = FALSE;\r
486 }\r
487\r
488 *NextString = String;\r
489\r
490 return RetVal;\r
491}\r
492\r
493/**\r
494 Extract Readonly flag from opcode.\r
495\r
496 This is a internal function.\r
497\r
498 @param OpCodeData Input opcode for this question.\r
499\r
500 @retval TRUE This question is readonly.\r
501 @retval FALSE This question is not readonly.\r
502\r
503**/\r
504BOOLEAN\r
505ExtractReadOnlyFromOpCode (\r
506 IN UINT8 *OpCodeData\r
507 )\r
508{\r
509 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
510\r
511 ASSERT (OpCodeData != NULL);\r
512\r
513 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
514\r
515 return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;\r
516}\r
517\r
518/**\r
519 Create a circuit to check the filter section.\r
520\r
521 This is a internal function.\r
522\r
4a429716 523 @param OpCodeData The question binary ifr data.\r
87bfeb11 524 @param KeywordRequest KeywordRequestformat string.\r
4a429716 525 @param NextString return the next string follow this keyword section.\r
87bfeb11
ED
526 @param ReadOnly Return whether this question is read only.\r
527\r
528 @retval KEYWORD_HANDLER_NO_ERROR Success validate.\r
529 @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.\r
530\r
531**/\r
532UINT32\r
533ValidateFilter (\r
534 IN UINT8 *OpCodeData,\r
535 IN CHAR16 *KeywordRequest,\r
536 OUT CHAR16 **NextString,\r
537 OUT BOOLEAN *ReadOnly\r
538 )\r
539{\r
540 CHAR16 *NextFilter;\r
541 CHAR16 *StringPtr;\r
542 UINT8 FilterFlags;\r
543 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
544 EFI_IFR_OP_HEADER *OpCodeHdr;\r
545 UINT8 Flags;\r
546 UINT32 RetVal;\r
547\r
548 RetVal = KEYWORD_HANDLER_NO_ERROR;\r
549 StringPtr = KeywordRequest;\r
550\r
551 OpCodeHdr = (EFI_IFR_OP_HEADER *) OpCodeData;\r
552 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
553 if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
554 Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));\r
555 } else {\r
556 Flags = 0;\r
557 }\r
558\r
559 //\r
560 // Get ReadOnly flag from Question.\r
561 // \r
562 *ReadOnly = ExtractReadOnlyFromOpCode(OpCodeData);\r
563\r
564 while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {\r
565 switch (FilterFlags) {\r
566 case EFI_KEYWORD_FILTER_READONY:\r
567 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {\r
568 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
569 goto Done;\r
570 }\r
571 break;\r
572\r
573 case EFI_KEYWORD_FILTER_REAWRITE:\r
574 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {\r
575 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
576 goto Done;\r
577 }\r
578 break;\r
579\r
580 case EFI_KEYWORD_FILTER_BUFFER:\r
581 //\r
582 // Only these three opcode use numeric value type.\r
583 //\r
584 if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP || OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP) {\r
585 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
586 goto Done;\r
587 }\r
588 break;\r
589\r
590 case EFI_KEYWORD_FILTER_NUMERIC:\r
591 if (OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP && OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP && OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP) {\r
592 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
593 goto Done;\r
594 }\r
595 break;\r
596\r
597 case EFI_KEYWORD_FILTER_NUMERIC_1:\r
598 case EFI_KEYWORD_FILTER_NUMERIC_2:\r
599 case EFI_KEYWORD_FILTER_NUMERIC_4:\r
600 case EFI_KEYWORD_FILTER_NUMERIC_8:\r
601 if (OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP && OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP && OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP) {\r
602 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
603 goto Done;\r
604 }\r
605\r
606 //\r
607 // For numeric and oneof, it has flags field to specify the detail numeric type.\r
608 //\r
609 if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
610 switch (Flags & EFI_IFR_NUMERIC_SIZE) {\r
611 case EFI_IFR_NUMERIC_SIZE_1:\r
612 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {\r
613 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
614 goto Done;\r
615 }\r
616 break;\r
617\r
618 case EFI_IFR_NUMERIC_SIZE_2:\r
619 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {\r
620 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
621 goto Done;\r
622 }\r
623 break;\r
624\r
625 case EFI_IFR_NUMERIC_SIZE_4:\r
626 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {\r
627 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
628 goto Done;\r
629 }\r
630 break;\r
631\r
632 case EFI_IFR_NUMERIC_SIZE_8:\r
633 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {\r
634 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
635 goto Done;\r
636 }\r
637 break;\r
638\r
639 default:\r
640 ASSERT (FALSE);\r
641 break;\r
642 }\r
643 }\r
644 break;\r
645\r
646 default:\r
647 ASSERT (FALSE);\r
648 break;\r
649 }\r
650\r
651 //\r
652 // Jump to the next filter.\r
653 //\r
654 StringPtr = NextFilter;\r
655 }\r
656 \r
657Done:\r
658 //\r
659 // The current filter which is processing.\r
660 //\r
661 *NextString = StringPtr;\r
662\r
663 return RetVal;\r
664}\r
665\r
666/**\r
667 Get HII_DATABASE_RECORD from the input device path info.\r
668\r
669 This is a internal function.\r
670\r
671 @param DevicePath UEFI device path protocol.\r
672\r
673 @retval Internal data base record.\r
674\r
675**/\r
676HII_DATABASE_RECORD *\r
677GetRecordFromDevicePath (\r
678 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
679 )\r
680{\r
681 LIST_ENTRY *Link;\r
682 UINT8 *DevicePathPkg;\r
683 UINT8 *CurrentDevicePath;\r
684 UINTN DevicePathSize;\r
685 HII_DATABASE_RECORD *TempDatabase;\r
686\r
687 ASSERT (DevicePath != NULL);\r
688\r
689 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
690 TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
691 DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;\r
692 if (DevicePathPkg != NULL) {\r
693 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
694 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
695 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {\r
696 return TempDatabase;\r
697 }\r
698 }\r
699 }\r
700\r
701 return NULL;\r
702}\r
703\r
704/**\r
705 Calculate the size of StringSrc and output it. Also copy string text from src \r
706 to dest.\r
707\r
708 This is a internal function.\r
709\r
710 @param StringSrc Points to current null-terminated string.\r
711 @param BufferSize Length of the buffer.\r
712 @param StringDest Buffer to store the string text. \r
713\r
4a429716 714 @retval EFI_SUCCESS The string text was outputted successfully.\r
87bfeb11
ED
715 @retval EFI_OUT_OF_RESOURCES Out of resource.\r
716\r
717**/\r
718EFI_STATUS\r
719GetUnicodeStringTextAndSize (\r
720 IN UINT8 *StringSrc,\r
721 OUT UINTN *BufferSize,\r
722 OUT EFI_STRING *StringDest\r
723 )\r
724{\r
725 UINTN StringSize;\r
726 UINT8 *StringPtr;\r
727\r
728 ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);\r
729\r
730 StringSize = sizeof (CHAR16);\r
731 StringPtr = StringSrc;\r
732 while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) {\r
733 StringSize += sizeof (CHAR16);\r
734 StringPtr += sizeof (CHAR16);\r
735 }\r
736\r
737 *StringDest = AllocatePool (StringSize);\r
738 if (*StringDest == NULL) {\r
739 return EFI_OUT_OF_RESOURCES;\r
740 }\r
741 \r
742 CopyMem (*StringDest, StringSrc, StringSize);\r
743\r
744 *BufferSize = StringSize;\r
745 return EFI_SUCCESS;\r
746}\r
747\r
748/**\r
749 Find the string id for the input keyword.\r
750\r
751 @param StringPackage Hii string package instance.\r
752 @param KeywordValue Input keyword value.\r
753 @param StringId The string's id, which is unique within PackageList.\r
754\r
755\r
756 @retval EFI_SUCCESS The string text and font is retrieved\r
757 successfully.\r
758 @retval EFI_NOT_FOUND The specified text or font info can not be found\r
759 out.\r
760 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
761 task.\r
762**/\r
763EFI_STATUS\r
764GetStringIdFromString (\r
765 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
766 IN CHAR16 *KeywordValue,\r
767 OUT EFI_STRING_ID *StringId\r
768 )\r
769{\r
770 UINT8 *BlockHdr;\r
771 EFI_STRING_ID CurrentStringId;\r
772 UINTN BlockSize;\r
773 UINTN Index;\r
774 UINT8 *StringTextPtr;\r
775 UINTN Offset;\r
776 UINT16 StringCount;\r
777 UINT16 SkipCount;\r
778 UINT8 Length8;\r
779 EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
780 UINT32 Length32;\r
781 UINTN StringSize;\r
782 CHAR16 *String;\r
783 CHAR8 *AsciiKeywordValue;\r
b68ccac1 784 UINTN KeywordValueSize;\r
87bfeb11
ED
785 EFI_STATUS Status;\r
786\r
787 ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);\r
788 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
789\r
790 CurrentStringId = 1;\r
791 Status = EFI_SUCCESS;\r
792 String = NULL;\r
793 BlockHdr = StringPackage->StringBlock;\r
794 BlockSize = 0;\r
795 Offset = 0;\r
796\r
797 //\r
798 // Make a ascii keyword value for later use.\r
799 //\r
b68ccac1
SZ
800 KeywordValueSize = StrLen (KeywordValue) + 1;\r
801 AsciiKeywordValue = AllocatePool (KeywordValueSize);\r
87bfeb11
ED
802 if (AsciiKeywordValue == NULL) {\r
803 return EFI_OUT_OF_RESOURCES;\r
804 }\r
b68ccac1 805 UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);\r
87bfeb11
ED
806\r
807 while (*BlockHdr != EFI_HII_SIBT_END) {\r
808 switch (*BlockHdr) {\r
809 case EFI_HII_SIBT_STRING_SCSU:\r
810 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
811 StringTextPtr = BlockHdr + Offset;\r
812 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
c2400145 813 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
87bfeb11
ED
814 *StringId = CurrentStringId;\r
815 goto Done;\r
816 }\r
817 CurrentStringId++;\r
818 break;\r
819\r
820 case EFI_HII_SIBT_STRING_SCSU_FONT:\r
821 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
822 StringTextPtr = BlockHdr + Offset;\r
c2400145 823 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
87bfeb11
ED
824 *StringId = CurrentStringId;\r
825 goto Done;\r
826 }\r
827 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
828 CurrentStringId++;\r
829 break;\r
830\r
831 case EFI_HII_SIBT_STRINGS_SCSU:\r
832 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
833 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
834 BlockSize += StringTextPtr - BlockHdr;\r
835\r
836 for (Index = 0; Index < StringCount; Index++) {\r
837 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
c2400145 838 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
87bfeb11
ED
839 *StringId = CurrentStringId;\r
840 goto Done;\r
841 }\r
842 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
843 CurrentStringId++;\r
844 }\r
845 break;\r
846\r
847 case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
848 CopyMem (\r
849 &StringCount,\r
850 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
851 sizeof (UINT16)\r
852 );\r
853 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
854 BlockSize += StringTextPtr - BlockHdr;\r
855\r
856 for (Index = 0; Index < StringCount; Index++) {\r
857 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
c2400145 858 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
87bfeb11
ED
859 *StringId = CurrentStringId;\r
860 goto Done;\r
861 }\r
862 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
863 CurrentStringId++;\r
864 }\r
865 break;\r
866\r
867 case EFI_HII_SIBT_STRING_UCS2:\r
868 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
869 StringTextPtr = BlockHdr + Offset;\r
870 //\r
871 // Use StringSize to store the size of the specified string, including the NULL\r
872 // terminator.\r
873 //\r
874 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
875 if (EFI_ERROR (Status)) {\r
876 goto Done;\r
877 }\r
763cfa73 878 ASSERT (String != NULL);\r
87bfeb11
ED
879 if (StrCmp(KeywordValue, String) == 0) {\r
880 *StringId = CurrentStringId;\r
881 goto Done;\r
882 }\r
883 BlockSize += Offset + StringSize;\r
884 CurrentStringId++;\r
885 break;\r
886\r
887 case EFI_HII_SIBT_STRING_UCS2_FONT:\r
888 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
889 StringTextPtr = BlockHdr + Offset;\r
890 //\r
891 // Use StringSize to store the size of the specified string, including the NULL\r
892 // terminator.\r
893 //\r
894 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
895 if (EFI_ERROR (Status)) {\r
896 goto Done;\r
897 }\r
763cfa73 898 ASSERT (String != NULL);\r
87bfeb11
ED
899 if (StrCmp(KeywordValue, String) == 0) {\r
900 *StringId = CurrentStringId;\r
901 goto Done;\r
902 }\r
903 BlockSize += Offset + StringSize;\r
904 CurrentStringId++;\r
905 break;\r
906\r
907 case EFI_HII_SIBT_STRINGS_UCS2:\r
908 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
909 StringTextPtr = BlockHdr + Offset;\r
910 BlockSize += Offset;\r
911 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
912 for (Index = 0; Index < StringCount; Index++) {\r
913 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
914 if (EFI_ERROR (Status)) {\r
915 goto Done;\r
916 }\r
763cfa73 917 ASSERT (String != NULL);\r
87bfeb11
ED
918 BlockSize += StringSize;\r
919 if (StrCmp(KeywordValue, String) == 0) {\r
920 *StringId = CurrentStringId;\r
921 goto Done;\r
922 }\r
923 StringTextPtr = StringTextPtr + StringSize;\r
924 CurrentStringId++;\r
925 }\r
926 break;\r
927\r
928 case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
929 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
930 StringTextPtr = BlockHdr + Offset;\r
931 BlockSize += Offset;\r
932 CopyMem (\r
933 &StringCount,\r
934 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
935 sizeof (UINT16)\r
936 );\r
937 for (Index = 0; Index < StringCount; Index++) {\r
938 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
939 if (EFI_ERROR (Status)) {\r
940 goto Done;\r
941 }\r
763cfa73 942 ASSERT (String != NULL);\r
87bfeb11
ED
943 BlockSize += StringSize;\r
944 if (StrCmp(KeywordValue, String) == 0) {\r
945 *StringId = CurrentStringId;\r
946 goto Done;\r
947 }\r
948 StringTextPtr = StringTextPtr + StringSize;\r
949 CurrentStringId++;\r
950 }\r
951 break;\r
952\r
953 case EFI_HII_SIBT_DUPLICATE:\r
954 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
955 CurrentStringId++;\r
956 break;\r
957\r
958 case EFI_HII_SIBT_SKIP1:\r
959 SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
960 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
961 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
962 break;\r
963\r
964 case EFI_HII_SIBT_SKIP2:\r
965 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
966 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
967 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
968 break;\r
969\r
970 case EFI_HII_SIBT_EXT1:\r
971 CopyMem (\r
972 &Length8,\r
973 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
974 sizeof (UINT8)\r
975 );\r
976 BlockSize += Length8;\r
977 break;\r
978\r
979 case EFI_HII_SIBT_EXT2:\r
980 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
981 BlockSize += Ext2.Length;\r
982 break;\r
983\r
984 case EFI_HII_SIBT_EXT4:\r
985 CopyMem (\r
986 &Length32,\r
987 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
988 sizeof (UINT32)\r
989 );\r
990\r
991 BlockSize += Length32;\r
992 break;\r
993\r
994 default:\r
995 break;\r
996 }\r
997\r
998 if (String != NULL) {\r
999 FreePool (String);\r
1000 String = NULL;\r
1001 }\r
1002\r
1003 BlockHdr = StringPackage->StringBlock + BlockSize;\r
1004 }\r
1005\r
1006 Status = EFI_NOT_FOUND;\r
1007\r
1008Done:\r
1009 if (AsciiKeywordValue != NULL) {\r
1010 FreePool (AsciiKeywordValue);\r
1011 }\r
1012 if (String != NULL) {\r
1013 FreePool (String);\r
1014 }\r
1015 return Status;\r
1016}\r
1017\r
1018/**\r
1019 Find the next valid string id for the input string id.\r
1020\r
1021 @param StringPackage Hii string package instance.\r
1022 @param StringId The current string id which is already got.\r
1023 1 means just begin to get the string id.\r
1024 @param KeywordValue Return the string for the next string id.\r
1025\r
1026\r
1027 @retval EFI_STRING_ID Not 0 means a valid stringid found.\r
1028 0 means not found a valid string id.\r
1029**/\r
1030EFI_STRING_ID\r
1031GetNextStringId (\r
1032 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
1033 IN EFI_STRING_ID StringId,\r
1034 OUT EFI_STRING *KeywordValue\r
1035 )\r
1036{\r
1037 UINT8 *BlockHdr;\r
1038 EFI_STRING_ID CurrentStringId;\r
1039 UINTN BlockSize;\r
1040 UINTN Index;\r
1041 UINT8 *StringTextPtr;\r
1042 UINTN Offset;\r
1043 UINT16 StringCount;\r
1044 UINT16 SkipCount;\r
1045 UINT8 Length8;\r
1046 EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
1047 UINT32 Length32;\r
1048 BOOLEAN FindString;\r
1049 UINTN StringSize;\r
1050 CHAR16 *String;\r
1051\r
1052 ASSERT (StringPackage != NULL);\r
1053 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
1054\r
1055 CurrentStringId = 1;\r
1056 FindString = FALSE;\r
1057 String = NULL;\r
1058\r
1059 //\r
1060 // Parse the string blocks to get the string text and font.\r
1061 //\r
1062 BlockHdr = StringPackage->StringBlock;\r
1063 BlockSize = 0;\r
1064 Offset = 0;\r
1065 while (*BlockHdr != EFI_HII_SIBT_END) {\r
1066 switch (*BlockHdr) {\r
1067 case EFI_HII_SIBT_STRING_SCSU:\r
1068 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
1069 StringTextPtr = BlockHdr + Offset;\r
1070 \r
1071 if (FindString) {\r
b68ccac1
SZ
1072 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1073 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1074 if (*KeywordValue == NULL) {\r
1075 return 0;\r
1076 }\r
b68ccac1 1077 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1078 return CurrentStringId;\r
1079 } else if (CurrentStringId == StringId) {\r
1080 FindString = TRUE;\r
1081 }\r
1082\r
1083 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1084 CurrentStringId++;\r
1085 break;\r
1086\r
1087 case EFI_HII_SIBT_STRING_SCSU_FONT:\r
1088 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
1089 StringTextPtr = BlockHdr + Offset;\r
1090 \r
1091 if (FindString) {\r
b68ccac1
SZ
1092 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1093 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1094 if (*KeywordValue == NULL) {\r
1095 return 0;\r
1096 }\r
b68ccac1 1097 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1098 return CurrentStringId;\r
1099 } else if (CurrentStringId == StringId) {\r
1100 FindString = TRUE;\r
1101 }\r
1102\r
1103 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1104 CurrentStringId++;\r
1105 break;\r
1106\r
1107 case EFI_HII_SIBT_STRINGS_SCSU:\r
1108 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1109 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
1110 BlockSize += StringTextPtr - BlockHdr;\r
1111\r
1112 for (Index = 0; Index < StringCount; Index++) {\r
1113 if (FindString) {\r
b68ccac1
SZ
1114 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1115 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1116 if (*KeywordValue == NULL) {\r
1117 return 0;\r
1118 }\r
b68ccac1 1119 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1120 return CurrentStringId;\r
1121 } else if (CurrentStringId == StringId) {\r
1122 FindString = TRUE;\r
1123 }\r
1124\r
1125 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1126 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1127 CurrentStringId++;\r
1128 }\r
1129 break;\r
1130\r
1131 case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
1132 CopyMem (\r
1133 &StringCount,\r
1134 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1135 sizeof (UINT16)\r
1136 );\r
1137 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
1138 BlockSize += StringTextPtr - BlockHdr;\r
1139\r
1140 for (Index = 0; Index < StringCount; Index++) {\r
1141 if (FindString) {\r
b68ccac1
SZ
1142 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1143 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
87bfeb11
ED
1144 if (*KeywordValue == NULL) {\r
1145 return 0;\r
1146 }\r
b68ccac1 1147 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
87bfeb11
ED
1148 return CurrentStringId;\r
1149 } else if (CurrentStringId == StringId) {\r
1150 FindString = TRUE;\r
1151 }\r
1152\r
1153 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1154 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1155 CurrentStringId++;\r
1156 }\r
1157 break;\r
1158\r
1159 case EFI_HII_SIBT_STRING_UCS2:\r
1160 Offset = sizeof (EFI_HII_STRING_BLOCK);\r
1161 StringTextPtr = BlockHdr + Offset;\r
1162 //\r
1163 // Use StringSize to store the size of the specified string, including the NULL\r
1164 // terminator.\r
1165 //\r
1166 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1167 if (FindString && (String != NULL) && (*String != L'\0')) {\r
1168 //\r
1169 // String protocol use this type for the string id which has value for other package.\r
1170 // It will allocate an empty string block for this string id. so here we also check\r
1171 // *String != L'\0' to prohibit this case.\r
1172 //\r
1173 *KeywordValue = String;\r
1174 return CurrentStringId;\r
1175 } else if (CurrentStringId == StringId) {\r
1176 FindString = TRUE;\r
1177 }\r
1178\r
1179 BlockSize += Offset + StringSize;\r
1180 CurrentStringId++;\r
1181 break;\r
1182\r
1183 case EFI_HII_SIBT_STRING_UCS2_FONT:\r
1184 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
1185 StringTextPtr = BlockHdr + Offset;\r
1186 //\r
1187 // Use StringSize to store the size of the specified string, including the NULL\r
1188 // terminator.\r
1189 //\r
1190 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1191 if (FindString) {\r
1192 *KeywordValue = String;\r
1193 return CurrentStringId;\r
1194 } else if (CurrentStringId == StringId) {\r
1195 FindString = TRUE;\r
1196 }\r
1197\r
1198 BlockSize += Offset + StringSize;\r
1199 CurrentStringId++;\r
1200 break;\r
1201\r
1202 case EFI_HII_SIBT_STRINGS_UCS2:\r
1203 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
1204 StringTextPtr = BlockHdr + Offset;\r
1205 BlockSize += Offset;\r
1206 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1207 for (Index = 0; Index < StringCount; Index++) {\r
1208 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String); \r
1209\r
1210 if (FindString) {\r
1211 *KeywordValue = String;\r
1212 return CurrentStringId;\r
1213 } else if (CurrentStringId == StringId) {\r
1214 FindString = TRUE;\r
1215 }\r
1216\r
1217 BlockSize += StringSize;\r
1218 StringTextPtr = StringTextPtr + StringSize;\r
1219 CurrentStringId++;\r
1220 }\r
1221 break;\r
1222\r
1223 case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
1224 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
1225 StringTextPtr = BlockHdr + Offset;\r
1226 BlockSize += Offset;\r
1227 CopyMem (\r
1228 &StringCount,\r
1229 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1230 sizeof (UINT16)\r
1231 );\r
1232 for (Index = 0; Index < StringCount; Index++) {\r
1233 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
1234 if (FindString) {\r
1235 *KeywordValue = String;\r
1236 return CurrentStringId;\r
1237 } else if (CurrentStringId == StringId) {\r
1238 FindString = TRUE;\r
1239 }\r
1240\r
1241 BlockSize += StringSize;\r
1242 StringTextPtr = StringTextPtr + StringSize;\r
1243 CurrentStringId++;\r
1244 }\r
1245 break;\r
1246\r
1247 case EFI_HII_SIBT_DUPLICATE:\r
1248 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
1249 CurrentStringId++;\r
1250 break;\r
1251\r
1252 case EFI_HII_SIBT_SKIP1:\r
1253 SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
1254 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
1255 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
1256 break;\r
1257\r
1258 case EFI_HII_SIBT_SKIP2:\r
1259 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
1260 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
1261 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
1262 break;\r
1263\r
1264 case EFI_HII_SIBT_EXT1:\r
1265 CopyMem (\r
1266 &Length8,\r
1267 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1268 sizeof (UINT8)\r
1269 );\r
1270 BlockSize += Length8;\r
1271 break;\r
1272\r
1273 case EFI_HII_SIBT_EXT2:\r
1274 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
1275 BlockSize += Ext2.Length;\r
1276 break;\r
1277\r
1278 case EFI_HII_SIBT_EXT4:\r
1279 CopyMem (\r
1280 &Length32,\r
1281 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
1282 sizeof (UINT32)\r
1283 );\r
1284\r
1285 BlockSize += Length32;\r
1286 break;\r
1287\r
1288 default:\r
1289 break;\r
1290 }\r
1291\r
1292 if (String != NULL) {\r
1293 FreePool (String);\r
1294 String = NULL;\r
1295 }\r
1296\r
1297 BlockHdr = StringPackage->StringBlock + BlockSize;\r
1298 }\r
1299\r
1300 return 0;\r
1301}\r
1302\r
1303/**\r
1304 Get string package from the input NameSpace string.\r
1305\r
1306 This is a internal function.\r
1307\r
1308 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
1309 @param NameSpace NameSpace format string.\r
1310 @param KeywordValue Keyword value.\r
1311 @param StringId String Id for this keyword.\r
1312\r
4a429716 1313 @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.\r
87bfeb11
ED
1314 @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.\r
1315 @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.\r
1316 @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.\r
1317\r
1318**/\r
1319UINT32\r
1320GetStringIdFromRecord (\r
1321 IN HII_DATABASE_RECORD *DatabaseRecord,\r
1322 IN CHAR8 **NameSpace,\r
1323 IN CHAR16 *KeywordValue,\r
1324 OUT EFI_STRING_ID *StringId\r
1325 )\r
1326{\r
1327 LIST_ENTRY *Link;\r
1328 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
1329 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
1330 EFI_STATUS Status;\r
1331 CHAR8 *Name;\r
5f25ead9 1332 UINT32 RetVal;\r
87bfeb11
ED
1333\r
1334 ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);\r
1335\r
1336 PackageListNode = DatabaseRecord->PackageList;\r
5f25ead9 1337 RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
87bfeb11
ED
1338\r
1339 if (*NameSpace != NULL) {\r
1340 Name = *NameSpace;\r
1341 } else {\r
1342 Name = UEFI_CONFIG_LANG;\r
1343 }\r
1344\r
1345 for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {\r
1346 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1347\r
1348 if (AsciiStrnCmp(Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {\r
1349 Status = GetStringIdFromString (StringPackage, KeywordValue, StringId); \r
1350 if (EFI_ERROR (Status)) {\r
6c20eda7 1351 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
87bfeb11
ED
1352 } else {\r
1353 if (*NameSpace == NULL) {\r
1354 *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
1355 if (*NameSpace == NULL) {\r
1356 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
1357 }\r
1358 }\r
1359 return KEYWORD_HANDLER_NO_ERROR;\r
1360 }\r
1361 }\r
1362 }\r
1363\r
5f25ead9 1364 return RetVal;\r
87bfeb11
ED
1365}\r
1366\r
1367/**\r
1368 Tell whether this Operand is an Statement OpCode.\r
1369\r
1370 @param Operand Operand of an IFR OpCode.\r
1371\r
1372 @retval TRUE This is an Statement OpCode.\r
1373 @retval FALSE Not an Statement OpCode.\r
1374\r
1375**/\r
1376BOOLEAN\r
1377IsStatementOpCode (\r
1378 IN UINT8 Operand\r
1379 )\r
1380{\r
1381 if ((Operand == EFI_IFR_SUBTITLE_OP) ||\r
1382 (Operand == EFI_IFR_TEXT_OP) ||\r
1383 (Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
1384 (Operand == EFI_IFR_REF_OP) ||\r
1385 (Operand == EFI_IFR_ACTION_OP) ||\r
1386 (Operand == EFI_IFR_NUMERIC_OP) ||\r
1387 (Operand == EFI_IFR_ORDERED_LIST_OP) ||\r
1388 (Operand == EFI_IFR_CHECKBOX_OP) ||\r
1389 (Operand == EFI_IFR_STRING_OP) ||\r
1390 (Operand == EFI_IFR_PASSWORD_OP) ||\r
1391 (Operand == EFI_IFR_DATE_OP) ||\r
1392 (Operand == EFI_IFR_TIME_OP) ||\r
1393 (Operand == EFI_IFR_GUID_OP) ||\r
1394 (Operand == EFI_IFR_ONE_OF_OP)) {\r
1395 return TRUE;\r
1396 }\r
1397\r
1398 return FALSE;\r
1399}\r
1400\r
1401/**\r
1402 Tell whether this Operand is an Statement OpCode.\r
1403\r
1404 @param Operand Operand of an IFR OpCode.\r
1405\r
1406 @retval TRUE This is an Statement OpCode.\r
1407 @retval FALSE Not an Statement OpCode.\r
1408\r
1409**/\r
1410BOOLEAN\r
1411IsStorageOpCode (\r
1412 IN UINT8 Operand\r
1413 )\r
1414{\r
1415 if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
1416 (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
1417 (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
1418 return TRUE;\r
1419 }\r
1420\r
1421 return FALSE;\r
1422}\r
1423\r
1424/**\r
1425 Base on the prompt string id to find the question.\r
1426\r
1427 @param FormPackage The input form package.\r
1428 @param KeywordStrId The input prompt string id for one question.\r
1429\r
1430 @retval the opcode for the question.\r
1431\r
1432**/\r
1433UINT8 * \r
1434FindQuestionFromStringId (\r
1435 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,\r
1436 IN EFI_STRING_ID KeywordStrId \r
1437 )\r
1438{\r
1439 UINT8 *OpCodeData;\r
1440 UINT32 Offset;\r
1441 EFI_IFR_STATEMENT_HEADER *StatementHeader;\r
1442 EFI_IFR_OP_HEADER *OpCodeHeader;\r
1443 UINT32 FormDataLen;\r
1444\r
1445 ASSERT (FormPackage != NULL);\r
1446\r
1447 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
1448 Offset = 0;\r
1449 while (Offset < FormDataLen) {\r
1450 OpCodeData = FormPackage->IfrData + Offset;\r
1451 OpCodeHeader = (EFI_IFR_OP_HEADER *) OpCodeData;\r
1452\r
1453 if (IsStatementOpCode(OpCodeHeader->OpCode)) {\r
1454 StatementHeader = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
1455 if (StatementHeader->Prompt == KeywordStrId) {\r
1456 return OpCodeData;\r
1457 }\r
1458 }\r
1459\r
1460 Offset += OpCodeHeader->Length;\r
1461 }\r
1462\r
1463 return NULL;\r
1464}\r
1465\r
1466/**\r
1467 Base on the varstore id to find the storage info.\r
1468\r
1469 @param FormPackage The input form package.\r
1470 @param VarStoreId The input storage id.\r
1471\r
1472 @retval the opcode for the storage.\r
1473\r
1474**/\r
1475UINT8 *\r
1476FindStorageFromVarId (\r
1477 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,\r
1478 IN EFI_VARSTORE_ID VarStoreId\r
1479 )\r
1480{\r
1481 UINT8 *OpCodeData;\r
1482 UINT32 Offset;\r
1483 EFI_IFR_OP_HEADER *OpCodeHeader;\r
1484 UINT32 FormDataLen;\r
1485\r
1486 ASSERT (FormPackage != NULL);\r
1487\r
1488 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
1489 Offset = 0;\r
1490 while (Offset < FormDataLen) {\r
1491 OpCodeData = FormPackage->IfrData + Offset;\r
1492 OpCodeHeader = (EFI_IFR_OP_HEADER *) OpCodeData;\r
1493\r
1494 if (IsStorageOpCode(OpCodeHeader->OpCode)) {\r
1495 switch (OpCodeHeader->OpCode) {\r
1496 case EFI_IFR_VARSTORE_OP:\r
1497 if (VarStoreId == ((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId) {\r
1498 return OpCodeData;\r
1499 }\r
1500 break;\r
1501\r
1502 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1503 if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId) {\r
1504 return OpCodeData;\r
1505 }\r
1506 break;\r
1507\r
1508 case EFI_IFR_VARSTORE_EFI_OP:\r
1509 if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId) {\r
1510 return OpCodeData;\r
1511 }\r
1512 break;\r
1513\r
1514 default:\r
1515 break;\r
1516 }\r
1517 }\r
1518\r
1519 Offset += OpCodeHeader->Length;\r
1520 }\r
1521\r
1522 return NULL;\r
1523}\r
1524\r
1525/**\r
1526 Get width info for one question.\r
1527\r
1528 @param OpCodeData The input opcode for one question.\r
1529\r
1530 @retval the width info for one question.\r
1531\r
1532**/\r
1533UINT16 \r
1534GetWidth (\r
1535 IN UINT8 *OpCodeData\r
1536 )\r
1537{\r
1538 UINT8 *NextOpCodeData;\r
1539\r
1540 ASSERT (OpCodeData != NULL);\r
1541\r
1542 switch (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode) {\r
1543 case EFI_IFR_REF_OP:\r
1544 return (UINT16) sizeof (EFI_HII_REF);\r
1545\r
1546 case EFI_IFR_ONE_OF_OP:\r
1547 case EFI_IFR_NUMERIC_OP:\r
1548 switch (((EFI_IFR_ONE_OF *) OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1549 case EFI_IFR_NUMERIC_SIZE_1:\r
1550 return (UINT16) sizeof (UINT8);\r
1551 \r
1552 case EFI_IFR_NUMERIC_SIZE_2:\r
1553 return (UINT16) sizeof (UINT16);\r
1554 \r
1555 case EFI_IFR_NUMERIC_SIZE_4:\r
1556 return (UINT16) sizeof (UINT32);\r
1557 \r
1558 case EFI_IFR_NUMERIC_SIZE_8:\r
1559 return (UINT16) sizeof (UINT64);\r
1560 \r
1561 default:\r
1562 ASSERT (FALSE);\r
1563 return 0;\r
1564 }\r
1565\r
1566 case EFI_IFR_ORDERED_LIST_OP:\r
1567 NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Header.Length;\r
1568 //\r
1569 // OneOfOption must follow the orderedlist opcode.\r
1570 //\r
1571 ASSERT (((EFI_IFR_OP_HEADER *) NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);\r
1572 switch (((EFI_IFR_ONE_OF_OPTION *) NextOpCodeData)->Type) {\r
1573 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1574 return (UINT16) sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
1575 \r
1576 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1577 return (UINT16) sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers ;\r
1578 \r
1579 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1580 return (UINT16) sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
1581 \r
1582 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1583 return (UINT16) sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
87bfeb11
ED
1584 \r
1585 default:\r
1586 ASSERT (FALSE);\r
1587 return 0;\r
1588 }\r
1589\r
1590 case EFI_IFR_CHECKBOX_OP:\r
1591 return (UINT16) sizeof (BOOLEAN);\r
1592 \r
1593 case EFI_IFR_PASSWORD_OP:\r
4858527b
DB
1594 return (UINT16)((UINTN) ((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize * sizeof (CHAR16));\r
1595\r
87bfeb11
ED
1596 case EFI_IFR_STRING_OP:\r
1597 return (UINT16)((UINTN) ((EFI_IFR_STRING *) OpCodeData)->MaxSize * sizeof (CHAR16));\r
1598\r
1599 case EFI_IFR_DATE_OP:\r
1600 return (UINT16) sizeof (EFI_HII_DATE);\r
1601\r
1602 case EFI_IFR_TIME_OP:\r
1603 return (UINT16) sizeof (EFI_HII_TIME);\r
1604\r
1605 default:\r
1606 ASSERT (FALSE);\r
1607 return 0;\r
1608 }\r
1609}\r
1610\r
1611/**\r
4a429716 1612 Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for\r
87bfeb11
ED
1613 hex digits that appear between a '=' and a '&' in a config string.\r
1614\r
1615 If ConfigString is NULL, then ASSERT().\r
1616\r
1617 @param[in] ConfigString Pointer to a Null-terminated Unicode string.\r
1618\r
1619 @return Pointer to the Null-terminated Unicode result string.\r
1620\r
1621**/\r
1622EFI_STRING\r
1623EFIAPI\r
1624InternalLowerConfigString (\r
1625 IN EFI_STRING ConfigString\r
1626 )\r
1627{\r
1628 EFI_STRING String;\r
1629 BOOLEAN Lower;\r
1630\r
1631 ASSERT (ConfigString != NULL);\r
1632\r
1633 //\r
1634 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
1635 //\r
1636 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
1637 if (*String == L'=') {\r
1638 Lower = TRUE;\r
1639 } else if (*String == L'&') {\r
1640 Lower = FALSE;\r
1641 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
1642 *String = (CHAR16) (*String - L'A' + L'a');\r
1643 }\r
1644 }\r
1645\r
1646 return ConfigString;\r
1647}\r
1648\r
1649/**\r
1650 Allocates and returns a Null-terminated Unicode <ConfigHdr> string.\r
1651 \r
1652 The format of a <ConfigHdr> is as follows:\r
1653\r
1654 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
1655\r
1656 @param[in] OpCodeData The opcode for the storage. \r
1657 @param[in] DriverHandle The driver handle which supports a Device Path Protocol\r
1658 that is the routing information PATH. Each byte of\r
1659 the Device Path associated with DriverHandle is converted\r
4a429716 1660 to a 2 Unicode character hexadecimal string.\r
87bfeb11
ED
1661\r
1662 @retval NULL DriverHandle does not support the Device Path Protocol.\r
1663 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string\r
1664\r
1665**/\r
1666EFI_STRING\r
1667ConstructConfigHdr (\r
1668 IN UINT8 *OpCodeData,\r
1669 IN EFI_HANDLE DriverHandle\r
1670 )\r
1671{\r
1672 UINTN NameLength;\r
1673 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1674 UINTN DevicePathSize;\r
1675 CHAR16 *String;\r
1676 CHAR16 *ReturnString;\r
1677 UINTN Index;\r
1678 UINT8 *Buffer;\r
1679 CHAR16 *Name;\r
1680 CHAR8 *AsciiName;\r
b68ccac1 1681 UINTN NameSize;\r
87bfeb11 1682 EFI_GUID *Guid;\r
5ad66ec6 1683 UINTN MaxLen;\r
87bfeb11
ED
1684\r
1685 ASSERT (OpCodeData != NULL);\r
1686\r
1687 switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {\r
1688 case EFI_IFR_VARSTORE_OP:\r
1689 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *) OpCodeData)->Guid;\r
c2400145 1690 AsciiName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
87bfeb11
ED
1691 break;\r
1692 \r
1693 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1694 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;\r
1695 AsciiName = NULL;\r
1696 break;\r
1697 \r
1698 case EFI_IFR_VARSTORE_EFI_OP:\r
1699 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;\r
c2400145 1700 AsciiName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;\r
87bfeb11
ED
1701 break;\r
1702 \r
1703 default:\r
1704 ASSERT (FALSE);\r
1705 Guid = NULL;\r
1706 AsciiName = NULL;\r
1707 break;\r
1708 }\r
1709\r
1710 if (AsciiName != NULL) {\r
b68ccac1
SZ
1711 NameSize = AsciiStrSize (AsciiName);\r
1712 Name = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
87bfeb11 1713 ASSERT (Name != NULL);\r
b68ccac1 1714 AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);\r
87bfeb11
ED
1715 } else {\r
1716 Name = NULL;\r
1717 }\r
1718\r
1719 //\r
1720 // Compute the length of Name in Unicode characters. \r
1721 // If Name is NULL, then the length is 0.\r
1722 //\r
1723 NameLength = 0;\r
1724 if (Name != NULL) {\r
1725 NameLength = StrLen (Name);\r
1726 }\r
1727\r
1728 DevicePath = NULL;\r
1729 DevicePathSize = 0;\r
1730 //\r
1731 // Retrieve DevicePath Protocol associated with DriverHandle\r
1732 //\r
1733 if (DriverHandle != NULL) {\r
1734 DevicePath = DevicePathFromHandle (DriverHandle);\r
1735 if (DevicePath == NULL) {\r
1736 return NULL;\r
1737 }\r
1738 //\r
1739 // Compute the size of the device path in bytes\r
1740 //\r
1741 DevicePathSize = GetDevicePathSize (DevicePath);\r
1742 }\r
1743\r
1744 //\r
1745 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
1746 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
1747 //\r
5ad66ec6
DB
1748 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
1749 String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
1750 if (String == NULL) {\r
1751 return NULL;\r
1752 }\r
1753\r
1754 //\r
1755 // Start with L"GUID="\r
1756 //\r
5ad66ec6
DB
1757 StrCpyS (String, MaxLen, L"GUID=");\r
1758 ReturnString = String;\r
87bfeb11
ED
1759 String += StrLen (String);\r
1760\r
1761 if (Guid != NULL) {\r
1762 //\r
1763 // Append Guid converted to <HexCh>32\r
1764 //\r
1765 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
9f4048f7
HW
1766 UnicodeValueToStringS (\r
1767 String,\r
1768 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1769 PREFIX_ZERO | RADIX_HEX,\r
1770 *(Buffer++),\r
1771 2\r
1772 );\r
1773 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1774 }\r
1775 }\r
1776 \r
1777 //\r
1778 // Append L"&NAME="\r
1779 //\r
2d3e4cd1 1780 StrCatS (ReturnString, MaxLen, L"&NAME=");\r
87bfeb11
ED
1781 String += StrLen (String);\r
1782\r
1783 if (Name != NULL) {\r
1784 //\r
1785 // Append Name converted to <Char>NameLength\r
1786 //\r
1787 for (; *Name != L'\0'; Name++) {\r
9f4048f7
HW
1788 UnicodeValueToStringS (\r
1789 String,\r
1790 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1791 PREFIX_ZERO | RADIX_HEX,\r
1792 *Name,\r
1793 4\r
1794 );\r
1795 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1796 }\r
1797 }\r
1798\r
1799 //\r
1800 // Append L"&PATH="\r
1801 //\r
2d3e4cd1 1802 StrCatS (ReturnString, MaxLen, L"&PATH=");\r
87bfeb11
ED
1803 String += StrLen (String);\r
1804\r
1805 //\r
1806 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
1807 //\r
1808 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
9f4048f7
HW
1809 UnicodeValueToStringS (\r
1810 String,\r
1811 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
1812 PREFIX_ZERO | RADIX_HEX,\r
1813 *(Buffer++),\r
1814 2\r
1815 );\r
1816 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
87bfeb11
ED
1817 }\r
1818\r
1819 //\r
1820 // Null terminate the Unicode string\r
1821 //\r
1822 *String = L'\0';\r
1823\r
1824 //\r
1825 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
1826 //\r
1827 return InternalLowerConfigString (ReturnString);\r
1828}\r
1829\r
1830/**\r
1831 Generate the Config request element for one question.\r
1832\r
1833 @param Name The name info for one question.\r
1834 @param Offset The offset info for one question.\r
1835 @param Width The width info for one question.\r
1836\r
1837 @return Pointer to the Null-terminated Unicode request element string.\r
1838\r
1839**/\r
1840EFI_STRING\r
1841ConstructRequestElement (\r
1842 IN CHAR16 *Name,\r
1843 IN UINT16 Offset,\r
1844 IN UINT16 Width \r
1845 )\r
1846{\r
1847 CHAR16 *StringPtr;\r
1848 UINTN Length;\r
1849 \r
1850 if (Name != NULL) {\r
1851 //\r
1852 // Add <BlockName> length for each Name\r
1853 //\r
1854 // <BlockName> ::= Name + \0\r
1855 // StrLen(Name) | 1\r
1856 //\r
1857 Length = StrLen (Name) + 1;\r
1858 } else {\r
1859 //\r
1860 // Add <BlockName> length for each Offset/Width pair\r
1861 //\r
1862 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0\r
1863 // | 7 | 4 | 7 | 4 | 1\r
1864 //\r
1865 Length = (7 + 4 + 7 + 4 + 1);\r
1866 }\r
1867\r
1868 //\r
1869 // Allocate buffer for the entire <ConfigRequest>\r
1870 //\r
1871 StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));\r
1872 ASSERT (StringPtr != NULL);\r
1873\r
1874 if (Name != NULL) {\r
1875 //\r
1876 // Append Name\0\r
1877 //\r
1878 UnicodeSPrint (\r
1879 StringPtr,\r
1880 (StrLen (Name) + 1) * sizeof (CHAR16),\r
1881 L"%s",\r
1882 Name\r
1883 );\r
1884 } else {\r
1885 //\r
1886 // Append OFFSET=XXXX&WIDTH=YYYY\0\r
1887 //\r
1888 UnicodeSPrint (\r
1889 StringPtr, \r
1890 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
1891 L"OFFSET=%04X&WIDTH=%04X", \r
1892 Offset, \r
1893 Width\r
1894 );\r
1895 }\r
1896\r
1897 return StringPtr;\r
1898}\r
1899\r
1900/**\r
1901 Get string value for question's name field.\r
1902\r
1903 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
1904 @param NameId The string id for the name field.\r
1905\r
1906 @retval Name string.\r
1907\r
1908**/\r
1909CHAR16 *\r
1910GetNameFromId (\r
1911 IN HII_DATABASE_RECORD *DatabaseRecord,\r
1912 IN EFI_STRING_ID NameId\r
1913 )\r
1914{\r
1915 CHAR16 *Name;\r
1916 CHAR8 *PlatformLanguage;\r
1917 CHAR8 *SupportedLanguages;\r
1918 CHAR8 *BestLanguage;\r
1919 UINTN StringSize;\r
1920 CHAR16 TempString;\r
1921 EFI_STATUS Status;\r
1922\r
1923 Name = NULL;\r
1924 BestLanguage = NULL;\r
1925 PlatformLanguage = NULL; \r
1926 SupportedLanguages = NULL;\r
1927\r
1928 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);\r
1929 SupportedLanguages = GetSupportedLanguages(DatabaseRecord->Handle);\r
1930\r
1931 //\r
1932 // Get the best matching language from SupportedLanguages\r
1933 //\r
1934 BestLanguage = GetBestLanguage (\r
1935 SupportedLanguages, \r
1936 FALSE, // RFC 4646 mode\r
1937 PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority\r
1938 SupportedLanguages, // Lowest priority \r
1939 NULL\r
1940 );\r
1941 if (BestLanguage == NULL) {\r
1942 BestLanguage = AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");\r
1943 ASSERT (BestLanguage != NULL);\r
1944 }\r
1945\r
1946 StringSize = 0;\r
1947 Status = mPrivate.HiiString.GetString (\r
1948 &mPrivate.HiiString,\r
1949 BestLanguage,\r
1950 DatabaseRecord->Handle,\r
1951 NameId,\r
1952 &TempString,\r
1953 &StringSize,\r
1954 NULL\r
1955 );\r
1956 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1957 goto Done;\r
1958 }\r
1959\r
1960 Name = AllocateZeroPool (StringSize);\r
1961 if (Name == NULL) {\r
1962 goto Done;\r
1963 }\r
1964\r
1965 Status = mPrivate.HiiString.GetString (\r
1966 &mPrivate.HiiString,\r
1967 BestLanguage,\r
1968 DatabaseRecord->Handle,\r
1969 NameId,\r
1970 Name,\r
1971 &StringSize,\r
1972 NULL\r
1973 );\r
1974\r
1975 if (EFI_ERROR (Status)) {\r
1976 FreePool (Name);\r
1977 Name = NULL;\r
1978 goto Done;\r
1979 }\r
1980\r
1981Done:\r
1982 if (SupportedLanguages != NULL) {\r
1983 FreePool(SupportedLanguages);\r
1984 }\r
1985 if (BestLanguage != NULL) {\r
1986 FreePool (BestLanguage);\r
1987 }\r
1988 if (PlatformLanguage != NULL) {\r
1989 FreePool (PlatformLanguage);\r
1990 }\r
1991\r
1992 return Name;\r
1993}\r
1994\r
1995/**\r
1996 Base on the input parameter to generate the ConfigRequest string.\r
1997\r
1998 This is a internal function.\r
1999\r
2000 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
2001 @param KeywordStrId Keyword string id.\r
2002 @param OpCodeData The IFR data for this question.\r
2003 @param ConfigRequest Return the generate ConfigRequest string.\r
2004\r
2005 @retval EFI_SUCCESS Generate ConfigResp string success.\r
2006 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.\r
2007 @retval EFI_NOT_FOUND Not found the question which use this string id\r
2008 as the prompt string id.\r
2009**/\r
2010EFI_STATUS\r
2011ExtractConfigRequest (\r
2012 IN HII_DATABASE_RECORD *DatabaseRecord,\r
2013 IN EFI_STRING_ID KeywordStrId,\r
2014 OUT UINT8 **OpCodeData,\r
2015 OUT EFI_STRING *ConfigRequest\r
2016 ) \r
2017{\r
2018 LIST_ENTRY *Link;\r
2019 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2020 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
2021 EFI_IFR_QUESTION_HEADER *Header;\r
2022 UINT8 *Storage;\r
2023 UINT8 *OpCode;\r
2024 CHAR16 *Name;\r
2025 UINT16 Offset;\r
2026 UINT16 Width;\r
2027 CHAR16 *ConfigHdr;\r
2028 CHAR16 *RequestElement;\r
5ad66ec6 2029 UINTN MaxLen;\r
87bfeb11
ED
2030 CHAR16 *StringPtr;\r
2031\r
2032 ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);\r
2033\r
2034 OpCode = NULL;\r
2035 Name = NULL;\r
2036 Width = 0;\r
2037 Offset = 0;\r
2038\r
2039 PackageListNode = DatabaseRecord->PackageList;\r
2040\r
2041 //\r
2042 // Search the languages in the specified packagelist.\r
2043 //\r
2044 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
2045 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
2046\r
2047 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
2048 if (OpCode != NULL) {\r
2049 *OpCodeData = OpCode;\r
2050 Header = (EFI_IFR_QUESTION_HEADER *) (OpCode + sizeof (EFI_IFR_OP_HEADER));\r
2051 //\r
2052 // Header->VarStoreId == 0 means no storage for this question.\r
2053 //\r
2054 ASSERT (Header->VarStoreId != 0);\r
2055 DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
2056 \r
2057 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
2058 ASSERT (Storage != NULL);\r
2059\r
2060 if (((EFI_IFR_OP_HEADER *) Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
2061 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
2062 } else {\r
2063 Offset = Header->VarStoreInfo.VarOffset;\r
2064 Width = GetWidth (OpCode);\r
2065 }\r
2066 RequestElement = ConstructRequestElement(Name, Offset, Width);\r
2067 ConfigHdr = ConstructConfigHdr(Storage, DatabaseRecord->DriverHandle);\r
cbbc454b 2068 ASSERT (ConfigHdr != NULL);\r
87bfeb11 2069\r
5ad66ec6
DB
2070 MaxLen = StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1;\r
2071 *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
2072 if (*ConfigRequest == NULL) {\r
2073 FreePool (ConfigHdr);\r
2074 FreePool (RequestElement);\r
2075 return EFI_OUT_OF_RESOURCES;\r
2076 }\r
2077 StringPtr = *ConfigRequest;\r
2078\r
5ad66ec6 2079 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
87bfeb11 2080\r
2d3e4cd1 2081 StrCatS (StringPtr, MaxLen, L"&");\r
87bfeb11 2082\r
2d3e4cd1 2083 StrCatS (StringPtr, MaxLen, RequestElement);\r
87bfeb11
ED
2084\r
2085 FreePool (ConfigHdr);\r
2086 FreePool (RequestElement);\r
2087\r
2088 return EFI_SUCCESS;\r
2089 }\r
2090 }\r
2091\r
2092 return EFI_NOT_FOUND;\r
2093}\r
2094\r
2095/**\r
2096 Base on the input parameter to generate the ConfigResp string.\r
2097\r
2098 This is a internal function.\r
2099\r
2100 @param DatabaseRecord HII_DATABASE_RECORD format string.\r
2101 @param KeywordStrId Keyword string id.\r
2102 @param ValueElement The value for the question which use keyword string id\r
2103 as the prompt string id.\r
2104 @param OpCodeData The IFR data for this question.\r
2105 @param ConfigResp Return the generate ConfigResp string.\r
2106\r
2107 @retval EFI_SUCCESS Generate ConfigResp string success.\r
2108 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.\r
2109 @retval EFI_NOT_FOUND Not found the question which use this string id\r
2110 as the prompt string id.\r
2111**/\r
2112EFI_STATUS\r
2113ExtractConfigResp (\r
2114 IN HII_DATABASE_RECORD *DatabaseRecord,\r
2115 IN EFI_STRING_ID KeywordStrId,\r
2116 IN EFI_STRING ValueElement,\r
2117 OUT UINT8 **OpCodeData,\r
2118 OUT EFI_STRING *ConfigResp\r
2119 ) \r
2120{\r
2121 LIST_ENTRY *Link;\r
2122 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2123 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
2124 EFI_IFR_QUESTION_HEADER *Header;\r
2125 UINT8 *Storage;\r
2126 UINT8 *OpCode;\r
2127 CHAR16 *Name;\r
2128 UINT16 Offset;\r
2129 UINT16 Width;\r
2130 CHAR16 *ConfigHdr;\r
2131 CHAR16 *RequestElement;\r
5ad66ec6 2132 UINTN MaxLen;\r
87bfeb11
ED
2133 CHAR16 *StringPtr;\r
2134\r
2135 ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));\r
2136\r
2137 OpCode = NULL;\r
2138 Name = NULL;\r
2139 Width = 0;\r
2140 Offset = 0;\r
2141\r
2142 PackageListNode = DatabaseRecord->PackageList;\r
2143\r
2144 //\r
2145 // Search the languages in the specified packagelist.\r
2146 //\r
2147 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
2148 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
2149\r
2150 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
2151 if (OpCode != NULL) {\r
2152 *OpCodeData = OpCode;\r
2153 Header = (EFI_IFR_QUESTION_HEADER *) (OpCode + sizeof (EFI_IFR_OP_HEADER));\r
2154 //\r
2155 // Header->VarStoreId == 0 means no storage for this question.\r
2156 //\r
2157 ASSERT (Header->VarStoreId != 0);\r
2158 DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
2159 \r
2160 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
2161 ASSERT (Storage != NULL);\r
2162\r
2163 if (((EFI_IFR_OP_HEADER *) Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
2164 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
2165 } else {\r
2166 Offset = Header->VarStoreInfo.VarOffset;\r
2167 Width = GetWidth (OpCode);\r
2168 }\r
2169 RequestElement = ConstructRequestElement(Name, Offset, Width);\r
2170\r
2171 ConfigHdr = ConstructConfigHdr(Storage, DatabaseRecord->DriverHandle);\r
cbbc454b 2172 ASSERT (ConfigHdr != NULL);\r
87bfeb11 2173\r
5ad66ec6
DB
2174 MaxLen = StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1 + StrLen (L"VALUE=") + StrLen(ValueElement) + 1;\r
2175 *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));\r
87bfeb11
ED
2176 if (*ConfigResp == NULL) {\r
2177 FreePool (ConfigHdr);\r
2178 FreePool (RequestElement);\r
2179 return EFI_OUT_OF_RESOURCES;\r
2180 }\r
2181 StringPtr = *ConfigResp;\r
2182\r
5ad66ec6 2183 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
87bfeb11 2184\r
2d3e4cd1 2185 StrCatS (StringPtr, MaxLen, L"&");\r
87bfeb11 2186\r
87bfeb11 2187\r
2d3e4cd1
DB
2188 StrCatS (StringPtr, MaxLen, RequestElement);\r
2189\r
2190 StrCatS (StringPtr, MaxLen, L"&");\r
2191\r
2192 StrCatS (StringPtr, MaxLen, L"VALUE=");\r
87bfeb11 2193\r
2d3e4cd1 2194 StrCatS (StringPtr, MaxLen, ValueElement);\r
87bfeb11
ED
2195\r
2196 FreePool (ConfigHdr);\r
2197 FreePool (RequestElement);\r
2198\r
2199 return EFI_SUCCESS;\r
2200 }\r
2201 }\r
2202\r
2203 return EFI_NOT_FOUND;\r
2204}\r
2205\r
2206/**\r
2207 Get the Value section from the Hii driver.\r
2208\r
2209 This is a internal function.\r
2210\r
2211 @param ConfigRequest The input ConfigRequest string.\r
2212 @param ValueElement The respond Value section from the hii driver.\r
2213\r
2214 @retval Misc value The error status return from ExtractConfig function.\r
2215 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated\r
2216 @retval EFI_SUCCESS Get the value section success.\r
2217\r
2218**/\r
2219EFI_STATUS\r
2220ExtractValueFromDriver (\r
2221 IN CHAR16 *ConfigRequest,\r
2222 OUT CHAR16 **ValueElement\r
2223 )\r
2224{\r
2225 EFI_STATUS Status;\r
2226 EFI_STRING Result;\r
2227 EFI_STRING Progress;\r
2228 CHAR16 *StringPtr;\r
2229 CHAR16 *StringEnd;\r
2230\r
2231 ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));\r
2232\r
2233 Status = mPrivate.ConfigRouting.ExtractConfig (\r
2234 &mPrivate.ConfigRouting,\r
2235 (EFI_STRING) ConfigRequest,\r
2236 &Progress,\r
2237 &Result\r
2238 );\r
2239 if (EFI_ERROR (Status)) {\r
2240 return Status;\r
2241 }\r
2242\r
2243 //\r
2244 // Find Value Section and return it.\r
2245 //\r
2246 StringPtr = StrStr (Result, L"&VALUE=");\r
2247 ASSERT (StringPtr != NULL);\r
2248 StringEnd = StrStr (StringPtr + 1, L"&");\r
2249 if (StringEnd != NULL) {\r
2250 *StringEnd = L'\0';\r
2251 }\r
2252\r
2253 *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);\r
2254 if (*ValueElement == NULL) {\r
2255 return EFI_OUT_OF_RESOURCES;\r
2256 }\r
2257\r
2258 if (StringEnd != NULL) {\r
2259 *StringEnd = L'&';\r
2260 }\r
2261 FreePool (Result);\r
2262\r
2263 return EFI_SUCCESS;\r
2264}\r
2265\r
2266/**\r
2267 Get EFI_STRING_ID info from the input device path, namespace and keyword.\r
2268\r
2269 This is a internal function.\r
2270\r
2271 @param DevicePath Input device path info.\r
2272 @param NameSpace NameSpace format string.\r
2273 @param KeywordData Keyword used to get string id.\r
2274 @param ProgressErr Return extra error type.\r
2275 @param KeywordStringId Return EFI_STRING_ID.\r
2276 @param DataBaseRecord DataBase record data for this driver.\r
2277\r
2278 @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.\r
2279 @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.\r
2280 @retval EFI_SUCCESS Find the EFI_STRING_ID.\r
2281\r
2282**/\r
2283EFI_STATUS\r
2284GetStringIdFromDatabase (\r
2285 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
2286 IN CHAR8 **NameSpace,\r
2287 IN CHAR16 *KeywordData,\r
2288 OUT UINT32 *ProgressErr,\r
2289 OUT EFI_STRING_ID *KeywordStringId,\r
2290 OUT HII_DATABASE_RECORD **DataBaseRecord\r
2291 )\r
2292{\r
2293 HII_DATABASE_RECORD *Record;\r
2294 LIST_ENTRY *Link;\r
2295 BOOLEAN FindNameSpace;\r
2296 EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;\r
2297 UINT8 *DevicePathPkg;\r
2298 UINTN DevicePathSize;\r
2299\r
2300 ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));\r
2301\r
2302 FindNameSpace = FALSE;\r
2303\r
2304 if (*DevicePath != NULL) {\r
2305 //\r
2306 // Get DataBaseRecord from device path protocol.\r
2307 //\r
2308 Record = GetRecordFromDevicePath(*DevicePath);\r
2309 if (Record == NULL) {\r
2310 //\r
2311 // Can't find the DatabaseRecord base on the input device path info.\r
2312 // NEED TO CONFIRM the return ProgressErr.\r
2313 //\r
2314 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2315 return EFI_INVALID_PARAMETER;\r
2316 }\r
2317\r
2318 //\r
2319 // Get string id from the record.\r
2320 //\r
2321 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
2322 switch (*ProgressErr) {\r
2323 case KEYWORD_HANDLER_NO_ERROR:\r
2324 *DataBaseRecord = Record;\r
2325 return EFI_SUCCESS;\r
2326\r
2327 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:\r
2328 return EFI_INVALID_PARAMETER;\r
2329\r
2330 default:\r
2331 ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);\r
2332 return EFI_NOT_FOUND;\r
2333 }\r
2334 } else {\r
2335 //\r
2336 // Find driver which matches the routing data.\r
2337 //\r
2338 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
2339 Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2340\r
2341 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
2342 if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {\r
2343 *DataBaseRecord = Record;\r
2344 \r
2345 if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {\r
2346 DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));\r
2347 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DestDevicePath);\r
2348 *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);\r
2349 if (*DevicePath == NULL) {\r
2350 return EFI_OUT_OF_RESOURCES;\r
2351 }\r
2352 } else {\r
2353 //\r
2354 // Need to verify this ASSERT.\r
2355 //\r
2356 ASSERT (FALSE);\r
2357 }\r
2358\r
2359 return EFI_SUCCESS;\r
2360 } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {\r
2361 return EFI_OUT_OF_RESOURCES;\r
2362 } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {\r
2363 FindNameSpace = TRUE;\r
2364 } \r
2365 }\r
2366\r
2367 //\r
2368 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.\r
2369 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.\r
2370 //\r
2371 if (FindNameSpace) {\r
2372 return EFI_NOT_FOUND;\r
2373 } else {\r
2374 return EFI_INVALID_PARAMETER;\r
2375 }\r
2376 }\r
2377}\r
2378\r
2379/**\r
4a429716 2380 Generate the KeywordResp String.\r
87bfeb11
ED
2381\r
2382 <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']\r
2383\r
2384 @param NameSpace NameSpace format string.\r
2385 @param DevicePath Input device path info.\r
2386 @param KeywordData Keyword used to get string id.\r
2387 @param ValueStr The value section for the keyword.\r
2388 @param ReadOnly Whether this value is readonly.\r
2389 @param KeywordResp Return the point to the KeywordResp string.\r
2390\r
2391 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2392 @retval EFI_SUCCESS Generate the KeywordResp string.\r
2393\r
2394**/\r
2395EFI_STATUS\r
2396GenerateKeywordResp (\r
2397 IN CHAR8 *NameSpace, \r
2398 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2399 IN EFI_STRING KeywordData,\r
2400 IN EFI_STRING ValueStr,\r
2401 IN BOOLEAN ReadOnly,\r
2402 OUT EFI_STRING *KeywordResp\r
2403 )\r
2404{\r
2405 UINTN RespStrLen;\r
2406 CHAR16 *RespStr;\r
2407 CHAR16 *PathHdr;\r
2408 CHAR16 *UnicodeNameSpace;\r
b68ccac1 2409 UINTN NameSpaceLength;\r
87bfeb11
ED
2410\r
2411 ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));\r
2412\r
2413 //\r
2414 // 1. Calculate the string length.\r
2415 //\r
2416 //\r
2417 // 1.1 NameSpaceId size.\r
2418 // 'NAMESPACE='<String>\r
2419 //\r
b68ccac1
SZ
2420 NameSpaceLength = AsciiStrLen (NameSpace);\r
2421 RespStrLen = 10 + NameSpaceLength;\r
2422 UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));\r
87bfeb11
ED
2423 if (UnicodeNameSpace == NULL) {\r
2424 return EFI_OUT_OF_RESOURCES;\r
2425 }\r
b68ccac1 2426 AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);\r
87bfeb11
ED
2427\r
2428 //\r
2429 // 1.2 PathHdr size.\r
2430 // PATH=<UEFI binary Device Path represented as hex number>'&'\r
2431 // Attention: The output include the '&' at the end.\r
2432 //\r
2433 GenerateSubStr (\r
2434 L"&PATH=",\r
2435 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
2436 (VOID *) DevicePath,\r
2437 1,\r
2438 &PathHdr\r
2439 );\r
2440 RespStrLen += StrLen (PathHdr);\r
2441\r
2442 //\r
4a429716 2443 // 1.3 Keyword section.\r
87bfeb11
ED
2444 // 'KEYWORD='<String>[':'<DecCh>(1/4)]\r
2445 //\r
2446 RespStrLen += 8 + StrLen (KeywordData);\r
2447\r
2448 //\r
2449 // 1.4 Value section.\r
2450 // ValueStr = '&VALUE='<Number>\r
2451 //\r
2452 RespStrLen += StrLen (ValueStr);\r
2453\r
2454 //\r
2455 // 1.5 ReadOnly Section.\r
2456 // '&READONLY'\r
2457 //\r
2458 if (ReadOnly) {\r
2459 RespStrLen += 9;\r
2460 }\r
2461\r
2462 //\r
5ad66ec6 2463 // 2. Allocate the buffer and create the KeywordResp string include '\0'.\r
87bfeb11 2464 //\r
5ad66ec6
DB
2465 RespStrLen += 1;\r
2466 *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));\r
87bfeb11
ED
2467 if (*KeywordResp == NULL) {\r
2468 if (UnicodeNameSpace != NULL) {\r
2469 FreePool (UnicodeNameSpace);\r
2470 }\r
2471\r
2472 return EFI_OUT_OF_RESOURCES;\r
2473 }\r
2474 RespStr = *KeywordResp;\r
2475\r
2476 //\r
2477 // 2.1 Copy NameSpaceId section.\r
2478 //\r
5ad66ec6 2479 StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");\r
2d3e4cd1
DB
2480\r
2481 StrCatS (RespStr, RespStrLen, UnicodeNameSpace);\r
87bfeb11
ED
2482\r
2483 //\r
2484 // 2.2 Copy PathHdr section.\r
2485 //\r
2d3e4cd1 2486 StrCatS (RespStr, RespStrLen, PathHdr);\r
87bfeb11
ED
2487\r
2488 //\r
2489 // 2.3 Copy Keyword section.\r
2490 //\r
2d3e4cd1
DB
2491 StrCatS (RespStr, RespStrLen, L"KEYWORD=");\r
2492\r
2493 StrCatS (RespStr, RespStrLen, KeywordData);\r
87bfeb11
ED
2494\r
2495 //\r
2496 // 2.4 Copy the Value section.\r
2497 //\r
2d3e4cd1 2498 StrCatS (RespStr, RespStrLen, ValueStr);\r
87bfeb11
ED
2499\r
2500 //\r
2501 // 2.5 Copy ReadOnly section if exist.\r
2502 //\r
2503 if (ReadOnly) {\r
2d3e4cd1 2504 StrCatS (RespStr, RespStrLen, L"&READONLY");\r
87bfeb11
ED
2505 }\r
2506\r
87bfeb11
ED
2507 if (UnicodeNameSpace != NULL) {\r
2508 FreePool (UnicodeNameSpace);\r
2509 }\r
2510 if (PathHdr != NULL) {\r
2511 FreePool (PathHdr);\r
2512 }\r
2513 \r
2514 return EFI_SUCCESS;\r
2515}\r
2516\r
2517/**\r
2518 Merge the KeywordResp String to MultiKeywordResp string.\r
2519\r
2520 This is a internal function.\r
2521\r
2522 @param MultiKeywordResp The existed multikeywordresp string.\r
2523 @param KeywordResp The input keywordResp string.\r
2524\r
2525 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2526 @retval EFI_SUCCESS Generate the MultiKeywordResp string.\r
2527\r
2528**/\r
2529EFI_STATUS\r
2530MergeToMultiKeywordResp (\r
2531 IN OUT EFI_STRING *MultiKeywordResp,\r
2532 IN EFI_STRING *KeywordResp\r
2533 )\r
2534{\r
2535 UINTN MultiKeywordRespLen;\r
2536 EFI_STRING StringPtr;\r
2537\r
2538 if (*MultiKeywordResp == NULL) {\r
2539 *MultiKeywordResp = *KeywordResp;\r
2540 *KeywordResp = NULL;\r
2541 return EFI_SUCCESS;\r
2542 }\r
2543\r
2544 MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);\r
2545\r
2546 StringPtr = AllocateCopyPool (MultiKeywordRespLen, *MultiKeywordResp);\r
2547 if (StringPtr == NULL) {\r
2548 return EFI_OUT_OF_RESOURCES;\r
2549 }\r
2550 \r
2551 FreePool (*MultiKeywordResp);\r
2552 *MultiKeywordResp = StringPtr;\r
2553\r
2d3e4cd1 2554 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");\r
87bfeb11 2555\r
2d3e4cd1 2556 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);\r
87bfeb11
ED
2557\r
2558 return EFI_SUCCESS;\r
2559}\r
2560\r
2561/**\r
2562 Enumerate all keyword in the system. \r
2563 \r
2564 If error occur when parse one keyword, just skip it and parse the next one. \r
2565\r
2566 This is a internal function.\r
2567\r
2568 @param NameSpace The namespace used to search the string.\r
2569 @param MultiResp Return the MultiKeywordResp string for the system.\r
6c20eda7 2570 @param ProgressErr Return the error status.\r
87bfeb11
ED
2571\r
2572 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.\r
2573 @retval EFI_SUCCESS Generate the MultiKeywordResp string.\r
2574 @retval EFI_NOT_FOUND No keyword found.\r
2575\r
2576**/\r
2577EFI_STATUS\r
2578EnumerateAllKeywords (\r
2579 IN CHAR8 *NameSpace,\r
6c20eda7
ED
2580 OUT EFI_STRING *MultiResp,\r
2581 OUT UINT32 *ProgressErr\r
87bfeb11
ED
2582 )\r
2583{\r
2584 LIST_ENTRY *Link;\r
2585 LIST_ENTRY *StringLink;\r
2586 UINT8 *DevicePathPkg;\r
2587 UINT8 *DevicePath;\r
2588 HII_DATABASE_RECORD *DataBaseRecord;\r
87bfeb11
ED
2589 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
2590 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
2591 CHAR8 *LocalNameSpace;\r
2592 EFI_STRING_ID NextStringId;\r
2593 EFI_STATUS Status;\r
c2400145 2594 UINT8 *OpCode;\r
87bfeb11
ED
2595 CHAR16 *ConfigRequest;\r
2596 CHAR16 *ValueElement;\r
2597 CHAR16 *KeywordResp;\r
2598 CHAR16 *MultiKeywordResp;\r
2599 CHAR16 *KeywordData;\r
2600 BOOLEAN ReadOnly;\r
6c20eda7 2601 BOOLEAN FindKeywordPackages;\r
87bfeb11
ED
2602\r
2603 DataBaseRecord = NULL;\r
87bfeb11
ED
2604 Status = EFI_SUCCESS;\r
2605 MultiKeywordResp = NULL;\r
2606 DevicePath = NULL;\r
2607 LocalNameSpace = NULL;\r
2608 ConfigRequest = NULL;\r
2609 ValueElement = NULL;\r
2610 KeywordResp = NULL;\r
6c20eda7 2611 FindKeywordPackages = FALSE;\r
87bfeb11
ED
2612\r
2613 if (NameSpace == NULL) {\r
2614 NameSpace = UEFI_CONFIG_LANG;\r
2615 }\r
2616\r
2617 //\r
2618 // Find driver which matches the routing data.\r
2619 //\r
2620 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
2621 DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
2622 if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {\r
2623 DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
87bfeb11
ED
2624 }\r
2625 PackageListNode = DataBaseRecord->PackageList;\r
2626\r
2627 for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {\r
2628 StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
2629\r
2630 //\r
2631 // Check whether has keyword string package.\r
2632 //\r
2633 if (AsciiStrnCmp(NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {\r
6c20eda7 2634 FindKeywordPackages = TRUE;\r
87bfeb11
ED
2635 //\r
2636 // Keep the NameSpace string.\r
2637 //\r
2638 LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
2639 if (LocalNameSpace == NULL) {\r
2640 return EFI_OUT_OF_RESOURCES;\r
2641 }\r
2642\r
2643 //\r
2644 // 1 means just begin the enumerate the valid string ids.\r
2645 // StringId == 1 is always used to save the language for this string package.\r
2646 // Any valid string start from 2. so here initial it to 1.\r
2647 //\r
2648 NextStringId = 1;\r
2649 \r
2650 //\r
2651 // Enumerate all valid stringid in the package.\r
2652 //\r
2653 while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {\r
2654 //\r
2655 // 3.3 Construct the ConfigRequest string.\r
2656 //\r
2657 Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);\r
2658 if (EFI_ERROR (Status)) {\r
2659 //\r
2660 // If can't generate ConfigRequest for this question, skip it and start the next.\r
2661 //\r
2662 goto Error;\r
2663 }\r
2664 \r
2665 //\r
2666 // 3.4 Extract Value for the input keyword.\r
2667 //\r
2668 Status = ExtractValueFromDriver(ConfigRequest, &ValueElement);\r
2669 if (EFI_ERROR (Status)) {\r
2670 if (Status != EFI_OUT_OF_RESOURCES) {\r
2671 //\r
2672 // If can't generate ConfigRequest for this question, skip it and start the next.\r
2673 //\r
2674 goto Error;\r
2675 }\r
2676 //\r
2677 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
2678 //\r
2679 goto Done;\r
2680 }\r
2681\r
2682 //\r
2683 // Extract readonly flag from opcode.\r
2684 //\r
2685 ReadOnly = ExtractReadOnlyFromOpCode(OpCode);\r
2686\r
2687 //\r
2688 // 5. Generate KeywordResp string.\r
2689 //\r
2690 ASSERT (DevicePath != NULL);\r
2691 Status = GenerateKeywordResp(LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
2692 if (Status != EFI_SUCCESS) {\r
2693 //\r
2694 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
2695 //\r
2696 goto Done;\r
2697 }\r
2698 \r
2699 //\r
2700 // 6. Merge to the MultiKeywordResp string.\r
2701 //\r
2702 Status = MergeToMultiKeywordResp(&MultiKeywordResp, &KeywordResp);\r
2703 if (EFI_ERROR (Status)) {\r
2704 goto Done;\r
2705 }\r
2706Error:\r
2707 //\r
2708 // Clean the temp buffer to later use again.\r
2709 //\r
2710 if (ConfigRequest != NULL) {\r
2711 FreePool (ConfigRequest);\r
2712 ConfigRequest = NULL;\r
2713 }\r
2714 if (ValueElement != NULL) {\r
2715 FreePool (ValueElement);\r
2716 ValueElement = NULL;\r
2717 }\r
2718 if (KeywordResp != NULL) {\r
2719 FreePool (KeywordResp);\r
2720 KeywordResp = NULL;\r
2721 } \r
2722 }\r
2723\r
2724 if (LocalNameSpace != NULL) {\r
2725 FreePool (LocalNameSpace);\r
2726 LocalNameSpace = NULL;\r
2727 }\r
2728 }\r
2729 } \r
2730 }\r
2731\r
2732 //\r
4a429716 2733 // return the already get MultiKeywordString even error occurred.\r
87bfeb11
ED
2734 //\r
2735 if (MultiKeywordResp == NULL) {\r
2736 Status = EFI_NOT_FOUND;\r
6c20eda7
ED
2737 if (!FindKeywordPackages) {\r
2738 *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
2739 } else {\r
2740 *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
2741 }\r
87bfeb11
ED
2742 } else {\r
2743 Status = EFI_SUCCESS;\r
2744 }\r
2745 *MultiResp = MultiKeywordResp;\r
2746 \r
2747Done:\r
2748 if (LocalNameSpace != NULL) {\r
2749 FreePool (LocalNameSpace);\r
2750 }\r
2751 if (ConfigRequest != NULL) {\r
2752 FreePool (ConfigRequest);\r
2753 }\r
2754 if (ValueElement != NULL) {\r
2755 FreePool (ValueElement);\r
2756 }\r
2757\r
2758 return Status;\r
2759}\r
2760\r
2761/**\r
2762\r
2763 This function accepts a <MultiKeywordResp> formatted string, finds the associated\r
2764 keyword owners, creates a <MultiConfigResp> string from it and forwards it to the\r
2765 EFI_HII_ROUTING_PROTOCOL.RouteConfig function.\r
2766 \r
2767 If there is an issue in resolving the contents of the KeywordString, then the \r
2768 function returns an error and also sets the Progress and ProgressErr with the \r
2769 appropriate information about where the issue occurred and additional data about\r
2770 the nature of the issue. \r
2771 \r
2772 In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND\r
2773 error is generated during processing the second or later keyword element, the system\r
2774 storage associated with earlier keywords is not modified. All elements of the \r
2775 KeywordString must successfully pass all tests for format and access prior to making\r
2776 any modifications to storage.\r
2777 \r
2778 In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString\r
2779 containing multiple keywords, the state of storage associated with earlier keywords\r
2780 is undefined.\r
2781\r
2782\r
2783 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
2784\r
2785 @param KeywordString A null-terminated string in <MultiKeywordResp> format. \r
2786\r
2787 @param Progress On return, points to a character in the KeywordString. \r
2788 Points to the string's NULL terminator if the request \r
2789 was successful. Points to the most recent '&' before \r
91af324d
DB
2790 the first failing name / value pair (or the beginning\r
2791 of the string if the failure is in the first name / value\r
2792 pair) if the request was not successful.\r
87bfeb11
ED
2793\r
2794 @param ProgressErr If during the processing of the KeywordString there was\r
2795 a failure, this parameter gives additional information \r
2796 about the possible source of the problem. The various \r
2797 errors are defined in "Related Definitions" below.\r
2798\r
2799\r
2800 @retval EFI_SUCCESS The specified action was completed successfully.\r
2801\r
2802 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
2803 1. KeywordString is NULL.\r
2804 2. Parsing of the KeywordString resulted in an \r
2805 error. See Progress and ProgressErr for more data.\r
2806\r
2807 @retval EFI_NOT_FOUND An element of the KeywordString was not found. \r
2808 See ProgressErr for more data.\r
2809\r
2810 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. \r
2811 See ProgressErr for more data.\r
2812 \r
2813 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr \r
2814 for more data.\r
2815\r
2816 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr\r
2817 for more data.\r
2818\r
2819**/\r
2820EFI_STATUS\r
2821EFIAPI \r
2822EfiConfigKeywordHandlerSetData (\r
2823 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
2824 IN CONST EFI_STRING KeywordString,\r
2825 OUT EFI_STRING *Progress,\r
2826 OUT UINT32 *ProgressErr\r
2827 )\r
2828{\r
2829 CHAR8 *NameSpace;\r
2830 EFI_STATUS Status;\r
2831 CHAR16 *StringPtr;\r
2832 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
9946c0a9 2833 CHAR16 *NextStringPtr;\r
87bfeb11
ED
2834 CHAR16 *KeywordData;\r
2835 EFI_STRING_ID KeywordStringId;\r
2836 UINT32 RetVal;\r
2837 HII_DATABASE_RECORD *DataBaseRecord;\r
2838 UINT8 *OpCode;\r
2839 CHAR16 *ConfigResp;\r
2840 CHAR16 *MultiConfigResp;\r
2841 CHAR16 *ValueElement;\r
2842 BOOLEAN ReadOnly;\r
2843 EFI_STRING InternalProgress;\r
9946c0a9 2844 CHAR16 *TempString;\r
580d230d 2845 CHAR16 *KeywordStartPos;\r
87bfeb11
ED
2846\r
2847 if (This == NULL || Progress == NULL || ProgressErr == NULL || KeywordString == NULL) {\r
2848 return EFI_INVALID_PARAMETER;\r
2849 }\r
2850\r
2851 *Progress = KeywordString;\r
2852 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
2853 Status = EFI_SUCCESS;\r
87bfeb11
ED
2854 MultiConfigResp = NULL;\r
2855 NameSpace = NULL;\r
2856 DevicePath = NULL;\r
2857 KeywordData = NULL;\r
2858 ValueElement = NULL;\r
2859 ConfigResp = NULL;\r
580d230d 2860 KeywordStartPos = NULL;\r
87bfeb11
ED
2861 KeywordStringId = 0;\r
2862\r
9946c0a9
ED
2863 //\r
2864 // Use temp string to avoid changing input string buffer.\r
2865 //\r
2866 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);\r
2867 ASSERT (TempString != NULL);\r
2868 StringPtr = TempString;\r
2869\r
87bfeb11
ED
2870 while ((StringPtr != NULL) && (*StringPtr != L'\0')) {\r
2871 //\r
2872 // 1. Get NameSpace from NameSpaceId keyword.\r
2873 //\r
2874 Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);\r
2875 if (EFI_ERROR (Status)) {\r
2876 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
e74c4279 2877 goto Done;\r
87bfeb11 2878 }\r
22950757 2879 ASSERT (NameSpace != NULL);\r
e74c4279
ED
2880 //\r
2881 // 1.1 Check whether the input namespace is valid.\r
2882 //\r
2883 if (AsciiStrnCmp(NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {\r
6c20eda7 2884 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
e74c4279
ED
2885 Status = EFI_INVALID_PARAMETER;\r
2886 goto Done;\r
2887 }\r
2888\r
87bfeb11
ED
2889 StringPtr = NextStringPtr;\r
2890\r
2891 //\r
2892 // 2. Get possible Device Path info from KeywordString.\r
2893 //\r
2894 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
2895 if (EFI_ERROR (Status)) {\r
2896 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2897 goto Done;\r
2898 }\r
2899 StringPtr = NextStringPtr;\r
2900\r
2901 //\r
2902 // 3. Extract keyword from the KeywordRequest string.\r
2903 //\r
580d230d 2904 KeywordStartPos = StringPtr;\r
87bfeb11
ED
2905 Status = ExtractKeyword(StringPtr, &KeywordData, &NextStringPtr);\r
2906 if (EFI_ERROR (Status)) {\r
2907 //\r
2908 // Can't find Keyword base on the input device path info.\r
2909 //\r
2910 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2911 Status = EFI_INVALID_PARAMETER;\r
2912 goto Done;\r
2913 }\r
2914 StringPtr = NextStringPtr;\r
2915\r
2916 //\r
2917 // 4. Extract Value from the KeywordRequest string.\r
2918 //\r
2919 Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);\r
2920 if (EFI_ERROR (Status)) {\r
2921 //\r
2922 // Can't find Value base on the input device path info.\r
2923 //\r
2924 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2925 Status = EFI_INVALID_PARAMETER;\r
2926 goto Done;\r
2927 }\r
2928 StringPtr = NextStringPtr;\r
2929\r
2930 //\r
5654835b 2931 // 5. Find READONLY tag.\r
87bfeb11 2932 //\r
5654835b 2933 if ((StringPtr != NULL) && StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0) {\r
87bfeb11 2934 ReadOnly = TRUE;\r
5654835b 2935 StringPtr += StrLen (L"&READONLY");\r
87bfeb11
ED
2936 } else {\r
2937 ReadOnly = FALSE;\r
2938 }\r
2939\r
2940 //\r
2941 // 6. Get EFI_STRING_ID for the input keyword.\r
2942 //\r
2943 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
2944 if (EFI_ERROR (Status)) {\r
2945 *ProgressErr = RetVal;\r
2946 goto Done;\r
2947 }\r
2948\r
2949 //\r
2950 // 7. Construct the ConfigRequest string.\r
2951 //\r
2952 Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);\r
2953 if (EFI_ERROR (Status)) {\r
2954 goto Done;\r
2955 }\r
2956\r
2957 //\r
2958 // 8. Check the readonly flag.\r
2959 //\r
2960 if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {\r
5654835b
DB
2961 //\r
2962 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.\r
2963 // If not, the input KeywordString must be incorrect, return the error status to caller.\r
2964 //\r
2965 *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
2966 Status = EFI_INVALID_PARAMETER;\r
2967 goto Done;\r
2968 }\r
2969 if (ReadOnly) {\r
580d230d
ED
2970 *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;\r
2971 Status = EFI_ACCESS_DENIED;\r
5654835b 2972 goto Done;\r
87bfeb11
ED
2973 }\r
2974 \r
2975 //\r
2976 // 9. Merge to the MultiKeywordResp string.\r
2977 //\r
2978 Status = MergeToMultiKeywordResp(&MultiConfigResp, &ConfigResp);\r
2979 if (EFI_ERROR (Status)) {\r
2980 goto Done;\r
2981 }\r
2982\r
2983 //\r
2984 // 10. Clean the temp buffer point.\r
2985 //\r
2986 FreePool (NameSpace);\r
2987 FreePool (DevicePath);\r
2988 FreePool (KeywordData);\r
2989 FreePool (ValueElement);\r
2990 NameSpace = NULL;\r
2991 DevicePath = NULL; \r
2992 KeywordData = NULL;\r
2993 ValueElement = NULL;\r
2994 if (ConfigResp != NULL) {\r
2995 FreePool (ConfigResp);\r
2996 ConfigResp = NULL;\r
2997 }\r
580d230d 2998 KeywordStartPos = NULL;\r
87bfeb11
ED
2999 }\r
3000\r
3001 //\r
3002 // 11. Set value to driver.\r
3003 //\r
3004 Status = mPrivate.ConfigRouting.RouteConfig(\r
3005 &mPrivate.ConfigRouting,\r
3006 (EFI_STRING) MultiConfigResp,\r
3007 &InternalProgress\r
3008 );\r
3009 if (EFI_ERROR (Status)) {\r
3010 Status = EFI_DEVICE_ERROR;\r
3011 goto Done;\r
3012 }\r
3013 \r
3014 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
3015\r
3016Done:\r
580d230d
ED
3017 if (KeywordStartPos != NULL) {\r
3018 *Progress = KeywordString + (KeywordStartPos - TempString);\r
3019 } else {\r
3020 *Progress = KeywordString + (StringPtr - TempString);\r
3021 }\r
3f4288fe 3022\r
9946c0a9
ED
3023 ASSERT (TempString != NULL);\r
3024 FreePool (TempString);\r
87bfeb11
ED
3025 if (NameSpace != NULL) {\r
3026 FreePool (NameSpace);\r
3027 }\r
3028 if (DevicePath != NULL) {\r
3029 FreePool (DevicePath);\r
3030 }\r
3031 if (KeywordData != NULL) {\r
3032 FreePool (KeywordData);\r
3033 }\r
3034 if (ValueElement != NULL) {\r
3035 FreePool (ValueElement);\r
3036 }\r
3037 if (ConfigResp != NULL) {\r
3038 FreePool (ConfigResp);\r
3039 }\r
3040 if (MultiConfigResp != NULL && MultiConfigResp != ConfigResp) {\r
3041 FreePool (MultiConfigResp);\r
3f4288fe 3042 }\r
580d230d 3043\r
87bfeb11
ED
3044 return Status;\r
3045}\r
3046\r
3047/**\r
3048\r
3049 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying \r
3050 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the\r
3051 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.\r
3052 \r
3053 If there is an issue in resolving the contents of the KeywordString, then the function\r
3054 returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the\r
3055 appropriate information about where the issue occurred and additional data about the\r
3056 nature of the issue.\r
3057 \r
3058 In the case when KeywordString is NULL, or contains multiple keywords, or when\r
3059 EFI_NOT_FOUND is generated while processing the keyword elements, the Results string\r
3060 contains values returned for all keywords processed prior to the keyword generating the \r
3061 error but no values for the keyword with error or any following keywords.\r
3062\r
3063 \r
3064 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
3065 \r
3066 @param NameSpaceId A null-terminated string containing the platform configuration\r
3067 language to search through in the system. If a NULL is passed\r
3068 in, then it is assumed that any platform configuration language\r
3069 with the prefix of "x-UEFI-" are searched.\r
3070 \r
3071 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a\r
3072 NULL is passed in the KeywordString field, all of the known \r
3073 keywords in the system for the NameSpaceId specified are \r
3074 returned in the Results field.\r
3075 \r
3076 @param Progress On return, points to a character in the KeywordString. Points\r
3077 to the string's NULL terminator if the request was successful. \r
91af324d
DB
3078 Points to the most recent '&' before the first failing name / value\r
3079 pair (or the beginning of the string if the failure is in the first\r
3080 name / value pair) if the request was not successful.\r
87bfeb11
ED
3081 \r
3082 @param ProgressErr If during the processing of the KeywordString there was a\r
3083 failure, this parameter gives additional information about the \r
3084 possible source of the problem. See the definitions in SetData()\r
3085 for valid value definitions.\r
3086 \r
3087 @param Results A null-terminated string in <MultiKeywordResp> format is returned\r
3088 which has all the values filled in for the keywords in the \r
3089 KeywordString. This is a callee-allocated field, and must be freed\r
3090 by the caller after being used. \r
3091\r
3092 @retval EFI_SUCCESS The specified action was completed successfully.\r
3093 \r
3094 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
4a429716 3095 1.Progress, ProgressErr, or Results is NULL.\r
87bfeb11
ED
3096 2.Parsing of the KeywordString resulted in an error. See\r
3097 Progress and ProgressErr for more data.\r
3098 \r
3099\r
3100 @retval EFI_NOT_FOUND An element of the KeywordString was not found. See\r
3101 ProgressErr for more data.\r
3102\r
3103 @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr\r
3104 for more data.\r
3105\r
3106 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See\r
3107 ProgressErr for more data.\r
3108 \r
3109 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for\r
3110 more data.\r
3111\r
3112 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr\r
3113 for more data.\r
3114\r
3115**/\r
3116EFI_STATUS\r
3117EFIAPI \r
3118EfiConfigKeywordHandlerGetData (\r
3119 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
3120 IN CONST EFI_STRING NameSpaceId, OPTIONAL\r
3121 IN CONST EFI_STRING KeywordString, OPTIONAL\r
3122 OUT EFI_STRING *Progress, \r
3123 OUT UINT32 *ProgressErr,\r
3124 OUT EFI_STRING *Results\r
3125 )\r
3126{\r
3127 CHAR8 *NameSpace;\r
3128 EFI_STATUS Status;\r
3129 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3130 HII_DATABASE_RECORD *DataBaseRecord;\r
3131 CHAR16 *StringPtr;\r
3132 CHAR16 *NextStringPtr; \r
3133 CHAR16 *KeywordData;\r
3134 EFI_STRING_ID KeywordStringId;\r
3135 UINT8 *OpCode;\r
3136 CHAR16 *ConfigRequest;\r
3137 CHAR16 *ValueElement;\r
3138 UINT32 RetVal;\r
3139 BOOLEAN ReadOnly;\r
3140 CHAR16 *KeywordResp;\r
3141 CHAR16 *MultiKeywordResp;\r
9946c0a9 3142 CHAR16 *TempString;\r
87bfeb11
ED
3143\r
3144 if (This == NULL || Progress == NULL || ProgressErr == NULL || Results == NULL) {\r
3145 return EFI_INVALID_PARAMETER;\r
3146 }\r
3147\r
3148 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
3149 Status = EFI_SUCCESS;\r
3150 DevicePath = NULL;\r
3151 NameSpace = NULL;\r
3152 KeywordData = NULL;\r
3153 ConfigRequest= NULL;\r
3154 StringPtr = KeywordString;\r
3155 ReadOnly = FALSE;\r
3156 MultiKeywordResp = NULL;\r
3157 KeywordStringId = 0;\r
9946c0a9 3158 TempString = NULL;\r
87bfeb11 3159\r
9946c0a9
ED
3160 //\r
3161 // Use temp string to avoid changing input string buffer.\r
3162 //\r
3163 if (NameSpaceId != NULL) {\r
3164 TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);\r
3165 ASSERT (TempString != NULL);\r
3166 }\r
87bfeb11
ED
3167 //\r
3168 // 1. Get NameSpace from NameSpaceId keyword.\r
3169 //\r
9946c0a9
ED
3170 Status = ExtractNameSpace (TempString, &NameSpace, NULL);\r
3171 if (TempString != NULL) {\r
3172 FreePool (TempString);\r
3173 TempString = NULL;\r
3174 }\r
87bfeb11 3175 if (EFI_ERROR (Status)) {\r
6c20eda7 3176 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
87bfeb11
ED
3177 return Status;\r
3178 }\r
e74c4279
ED
3179 //\r
3180 // 1.1 Check whether the input namespace is valid.\r
3181 //\r
22950757
DB
3182 if (NameSpace != NULL){\r
3183 if (AsciiStrnCmp(NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {\r
6c20eda7 3184 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
22950757
DB
3185 return EFI_INVALID_PARAMETER;\r
3186 }\r
e74c4279
ED
3187 }\r
3188 \r
87bfeb11 3189 if (KeywordString != NULL) {\r
9946c0a9
ED
3190 //\r
3191 // Use temp string to avoid changing input string buffer.\r
3192 //\r
3193 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);\r
3194 ASSERT (TempString != NULL);\r
3195 StringPtr = TempString;\r
87bfeb11
ED
3196\r
3197 while (*StringPtr != L'\0') {\r
3198 //\r
3199 // 2. Get possible Device Path info from KeywordString.\r
3200 //\r
3201 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
3202 if (EFI_ERROR (Status)) {\r
3203 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
3204 goto Done;\r
3205 }\r
3206 StringPtr = NextStringPtr;\r
3207\r
3208 \r
3209 //\r
3210 // 3. Process Keyword section from the input keywordRequest string.\r
3211 //\r
3212 // 3.1 Extract keyword from the KeywordRequest string.\r
3213 //\r
3214 Status = ExtractKeyword(StringPtr, &KeywordData, &NextStringPtr);\r
3215 if (EFI_ERROR (Status)) {\r
3216 //\r
3217 // Can't find Keyword base on the input device path info.\r
3218 //\r
3219 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
3220 Status = EFI_INVALID_PARAMETER;\r
3221 goto Done;\r
3222 }\r
3223\r
3224 //\r
3225 // 3.2 Get EFI_STRING_ID for the input keyword.\r
3226 //\r
3227 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
3228 if (EFI_ERROR (Status)) {\r
3229 *ProgressErr = RetVal;\r
3230 goto Done;\r
3231 }\r
3232\r
3233 //\r
3234 // 3.3 Construct the ConfigRequest string.\r
3235 //\r
3236 Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);\r
3237 if (EFI_ERROR (Status)) {\r
3238 goto Done;\r
3239 }\r
3240 \r
3241 //\r
3242 // 3.4 Extract Value for the input keyword.\r
3243 //\r
3244 Status = ExtractValueFromDriver(ConfigRequest, &ValueElement);\r
3245 if (EFI_ERROR (Status)) {\r
3246 if (Status != EFI_OUT_OF_RESOURCES) {\r
3247 Status = EFI_DEVICE_ERROR;\r
3248 }\r
3249 goto Done;\r
3250 }\r
3251 StringPtr = NextStringPtr;\r
3252\r
3253 //\r
3254 // 4. Process the possible filter section.\r
3255 //\r
3256 RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);\r
3257 if (RetVal != KEYWORD_HANDLER_NO_ERROR) {\r
3258 *ProgressErr = RetVal;\r
3259 Status = EFI_INVALID_PARAMETER;\r
3260 goto Done;\r
3261 }\r
3262 StringPtr = NextStringPtr;\r
3263\r
3264\r
3265 //\r
3266 // 5. Generate KeywordResp string.\r
3267 //\r
3268 Status = GenerateKeywordResp(NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
3269 if (Status != EFI_SUCCESS) {\r
3270 goto Done;\r
3271 }\r
3272\r
3273 //\r
3274 // 6. Merge to the MultiKeywordResp string.\r
3275 //\r
3276 Status = MergeToMultiKeywordResp(&MultiKeywordResp, &KeywordResp);\r
3277 if (EFI_ERROR (Status)) {\r
3278 goto Done;\r
3279 }\r
3280\r
3281 //\r
3282 // 7. Update return value.\r
3283 //\r
3284 *Results = MultiKeywordResp;\r
3285\r
3286 //\r
3287 // 8. Clean the temp buffer.\r
3288 //\r
3289 FreePool (DevicePath);\r
3290 FreePool (KeywordData);\r
3291 FreePool (ValueElement);\r
3292 FreePool (ConfigRequest);\r
3293 DevicePath = NULL; \r
3294 KeywordData = NULL;\r
3295 ValueElement = NULL;\r
3296 ConfigRequest = NULL;\r
3297 if (KeywordResp != NULL) {\r
3298 FreePool (KeywordResp);\r
3299 KeywordResp = NULL;\r
3300 }\r
3301 }\r
3302 } else {\r
3303 //\r
3304 // Enumerate all keyword in the system.\r
3305 //\r
6c20eda7 3306 Status = EnumerateAllKeywords(NameSpace, &MultiKeywordResp, ProgressErr);\r
87bfeb11
ED
3307 if (EFI_ERROR (Status)) {\r
3308 goto Done;\r
3309 }\r
3310 *Results = MultiKeywordResp;\r
3311 }\r
3312\r
3313 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
3314\r
3315Done:\r
3f4288fe
ED
3316 *Progress = KeywordString + (StringPtr - TempString);\r
3317\r
9946c0a9
ED
3318 if (TempString != NULL) {\r
3319 FreePool (TempString);\r
3320 }\r
87bfeb11
ED
3321 if (NameSpace != NULL) {\r
3322 FreePool (NameSpace);\r
3323 }\r
3324 if (DevicePath != NULL) {\r
3325 FreePool (DevicePath);\r
3326 }\r
3327 if (KeywordData != NULL) {\r
3328 FreePool (KeywordData);\r
3329 }\r
3f4288fe 3330\r
87bfeb11
ED
3331 return Status;\r
3332}\r