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