]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigKeywordHandler.c
... / ...
CommitLineData
1/** @file\r
2Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.\r
3\r
4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
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
25 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.\r
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
106\r
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
116\r
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
130\r
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
175 UINTN NameSpaceSize;\r
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
206 *TmpPtr = 0;\r
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
216 NameSpaceSize = StrLen (String) + 1;\r
217 *NameSpace = AllocatePool (NameSpaceSize);\r
218 if (*NameSpace == NULL) {\r
219 return EFI_OUT_OF_RESOURCES;\r
220 }\r
221 UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);\r
222\r
223 if (TmpPtr != NULL) {\r
224 *TmpPtr = L'&';\r
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
237 @param NextString return the next string follow this keyword section.\r
238\r
239 @retval EFI_SUCCESS Success to get the keyword string.\r
240 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
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
253\r
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
277\r
278 TmpPtr = StrStr (String, L"&");\r
279 if (TmpPtr != NULL) {\r
280 *TmpPtr = 0;\r
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
292\r
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
303 @param NextString return the next string follow this keyword section.\r
304\r
305 @retval EFI_SUCCESS Success to get the keyword string.\r
306 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
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
332\r
333 TmpPtr = StrStr (String, L"&");\r
334 if (TmpPtr != NULL) {\r
335 *TmpPtr = 0;\r
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
347\r
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
358 @param NextString return the next string follow this keyword section.\r
359\r
360 @retval EFI_SUCCESS Success to get the keyword string.\r
361 @retval EFI_INVALID_PARAMETER Parse the input string return error.\r
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
373 BOOLEAN RetVal;\r
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
384\r
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
474 // Only has platform defined filter section, just skip it.\r
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
517 @param OpCodeData The question binary ifr data.\r
518 @param KeywordRequest KeywordRequestformat string.\r
519 @param NextString return the next string follow this keyword section.\r
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
555 //\r
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
650\r
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
699 Calculate the size of StringSrc and output it. Also copy string text from src\r
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
706 @param StringDest Buffer to store the string text.\r
707\r
708 @retval EFI_SUCCESS The string text was outputted successfully.\r
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
735\r
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
778 UINTN KeywordValueSize;\r
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
794 KeywordValueSize = StrLen (KeywordValue) + 1;\r
795 AsciiKeywordValue = AllocatePool (KeywordValueSize);\r
796 if (AsciiKeywordValue == NULL) {\r
797 return EFI_OUT_OF_RESOURCES;\r
798 }\r
799 UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);\r
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
807 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
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
817 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
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
832 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
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
852 if (AsciiStrCmp(AsciiKeywordValue, (CHAR8 *) StringTextPtr) == 0) {\r
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
872 ASSERT (String != NULL);\r
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
892 ASSERT (String != NULL);\r
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
911 ASSERT (String != NULL);\r
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
936 ASSERT (String != NULL);\r
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
1064\r
1065 if (FindString) {\r
1066 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1067 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1068 if (*KeywordValue == NULL) {\r
1069 return 0;\r
1070 }\r
1071 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
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
1084\r
1085 if (FindString) {\r
1086 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1087 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1088 if (*KeywordValue == NULL) {\r
1089 return 0;\r
1090 }\r
1091 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
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
1108 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1109 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1110 if (*KeywordValue == NULL) {\r
1111 return 0;\r
1112 }\r
1113 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
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
1136 StringSize = AsciiStrSize ((CHAR8 *) StringTextPtr);\r
1137 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));\r
1138 if (*KeywordValue == NULL) {\r
1139 return 0;\r
1140 }\r
1141 AsciiStrToUnicodeStrS ((CHAR8 *) StringTextPtr, *KeywordValue, StringSize);\r
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
1202 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
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
1307 @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.\r
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
1326 UINT32 RetVal;\r
1327\r
1328 ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);\r
1329\r
1330 PackageListNode = DatabaseRecord->PackageList;\r
1331 RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
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
1343 Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);\r
1344 if (EFI_ERROR (Status)) {\r
1345 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
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
1358 return RetVal;\r
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
1427UINT8 *\r
1428FindQuestionFromStringId (\r
1429 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,\r
1430 IN EFI_STRING_ID KeywordStrId\r
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
1527UINT16\r
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
1545\r
1546 case EFI_IFR_NUMERIC_SIZE_2:\r
1547 return (UINT16) sizeof (UINT16);\r
1548\r
1549 case EFI_IFR_NUMERIC_SIZE_4:\r
1550 return (UINT16) sizeof (UINT32);\r
1551\r
1552 case EFI_IFR_NUMERIC_SIZE_8:\r
1553 return (UINT16) sizeof (UINT64);\r
1554\r
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
1569\r
1570 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1571 return (UINT16) sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers ;\r
1572\r
1573 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1574 return (UINT16) sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
1575\r
1576 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1577 return (UINT16) sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
1578\r
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
1586\r
1587 case EFI_IFR_PASSWORD_OP:\r
1588 return (UINT16)((UINTN) ((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize * sizeof (CHAR16));\r
1589\r
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
1606 Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for\r
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
1645\r
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
1650 @param[in] OpCodeData The opcode for the storage.\r
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
1654 to a 2 Unicode character hexadecimal string.\r
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
1675 UINTN NameSize;\r
1676 EFI_GUID *Guid;\r
1677 UINTN MaxLen;\r
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
1684 AsciiName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
1685 break;\r
1686\r
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
1691\r
1692 case EFI_IFR_VARSTORE_EFI_OP:\r
1693 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;\r
1694 AsciiName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;\r
1695 break;\r
1696\r
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
1705 NameSize = AsciiStrSize (AsciiName);\r
1706 Name = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
1707 ASSERT (Name != NULL);\r
1708 AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);\r
1709 } else {\r
1710 Name = NULL;\r
1711 }\r
1712\r
1713 //\r
1714 // Compute the length of Name in Unicode characters.\r
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
1742 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
1743 String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
1744 if (String == NULL) {\r
1745 return NULL;\r
1746 }\r
1747\r
1748 //\r
1749 // Start with L"GUID="\r
1750 //\r
1751 StrCpyS (String, MaxLen, L"GUID=");\r
1752 ReturnString = String;\r
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
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
1768 }\r
1769 }\r
1770\r
1771 //\r
1772 // Append L"&NAME="\r
1773 //\r
1774 StrCatS (ReturnString, MaxLen, L"&NAME=");\r
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
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
1790 }\r
1791 }\r
1792\r
1793 //\r
1794 // Append L"&PATH="\r
1795 //\r
1796 StrCatS (ReturnString, MaxLen, L"&PATH=");\r
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
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
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
1838 IN UINT16 Width\r
1839 )\r
1840{\r
1841 CHAR16 *StringPtr;\r
1842 UINTN Length;\r
1843\r
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
1883 StringPtr,\r
1884 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),\r
1885 L"OFFSET=%04X&WIDTH=%04X",\r
1886 Offset,\r
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
1919 PlatformLanguage = NULL;\r
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
1929 SupportedLanguages,\r
1930 FALSE, // RFC 4646 mode\r
1931 PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority\r
1932 SupportedLanguages, // Lowest priority\r
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
2010 )\r
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
2023 UINTN MaxLen;\r
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
2050\r
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
2062 ASSERT (ConfigHdr != NULL);\r
2063\r
2064 MaxLen = StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1;\r
2065 *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));\r
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
2073 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
2074\r
2075 StrCatS (StringPtr, MaxLen, L"&");\r
2076\r
2077 StrCatS (StringPtr, MaxLen, RequestElement);\r
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
2113 )\r
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
2126 UINTN MaxLen;\r
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
2153\r
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
2166 ASSERT (ConfigHdr != NULL);\r
2167\r
2168 MaxLen = StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1 + StrLen (L"VALUE=") + StrLen(ValueElement) + 1;\r
2169 *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));\r
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
2177 StrCpyS (StringPtr, MaxLen, ConfigHdr);\r
2178\r
2179 StrCatS (StringPtr, MaxLen, L"&");\r
2180\r
2181\r
2182 StrCatS (StringPtr, MaxLen, RequestElement);\r
2183\r
2184 StrCatS (StringPtr, MaxLen, L"&");\r
2185\r
2186 StrCatS (StringPtr, MaxLen, L"VALUE=");\r
2187\r
2188 StrCatS (StringPtr, MaxLen, ValueElement);\r
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
2338\r
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
2358 }\r
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
2374 Generate the KeywordResp String.\r
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
2391 IN CHAR8 *NameSpace,\r
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
2403 UINTN NameSpaceLength;\r
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
2414 NameSpaceLength = AsciiStrLen (NameSpace);\r
2415 RespStrLen = 10 + NameSpaceLength;\r
2416 UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));\r
2417 if (UnicodeNameSpace == NULL) {\r
2418 return EFI_OUT_OF_RESOURCES;\r
2419 }\r
2420 AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);\r
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
2437 // 1.3 Keyword section.\r
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
2457 // 2. Allocate the buffer and create the KeywordResp string include '\0'.\r
2458 //\r
2459 RespStrLen += 1;\r
2460 *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));\r
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
2473 StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");\r
2474\r
2475 StrCatS (RespStr, RespStrLen, UnicodeNameSpace);\r
2476\r
2477 //\r
2478 // 2.2 Copy PathHdr section.\r
2479 //\r
2480 StrCatS (RespStr, RespStrLen, PathHdr);\r
2481\r
2482 //\r
2483 // 2.3 Copy Keyword section.\r
2484 //\r
2485 StrCatS (RespStr, RespStrLen, L"KEYWORD=");\r
2486\r
2487 StrCatS (RespStr, RespStrLen, KeywordData);\r
2488\r
2489 //\r
2490 // 2.4 Copy the Value section.\r
2491 //\r
2492 StrCatS (RespStr, RespStrLen, ValueStr);\r
2493\r
2494 //\r
2495 // 2.5 Copy ReadOnly section if exist.\r
2496 //\r
2497 if (ReadOnly) {\r
2498 StrCatS (RespStr, RespStrLen, L"&READONLY");\r
2499 }\r
2500\r
2501 if (UnicodeNameSpace != NULL) {\r
2502 FreePool (UnicodeNameSpace);\r
2503 }\r
2504 if (PathHdr != NULL) {\r
2505 FreePool (PathHdr);\r
2506 }\r
2507\r
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
2540 StringPtr = ReallocatePool (\r
2541 StrSize (*MultiKeywordResp),\r
2542 MultiKeywordRespLen,\r
2543 *MultiKeywordResp\r
2544 );\r
2545 if (StringPtr == NULL) {\r
2546 return EFI_OUT_OF_RESOURCES;\r
2547 }\r
2548\r
2549 *MultiKeywordResp = StringPtr;\r
2550\r
2551 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");\r
2552\r
2553 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);\r
2554\r
2555 return EFI_SUCCESS;\r
2556}\r
2557\r
2558/**\r
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
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
2567 @param ProgressErr Return the error status.\r
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
2577 OUT EFI_STRING *MultiResp,\r
2578 OUT UINT32 *ProgressErr\r
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
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
2591 UINT8 *OpCode;\r
2592 CHAR16 *ConfigRequest;\r
2593 CHAR16 *ValueElement;\r
2594 CHAR16 *KeywordResp;\r
2595 CHAR16 *MultiKeywordResp;\r
2596 CHAR16 *KeywordData;\r
2597 BOOLEAN ReadOnly;\r
2598 BOOLEAN FindKeywordPackages;\r
2599\r
2600 DataBaseRecord = NULL;\r
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
2608 FindKeywordPackages = FALSE;\r
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
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
2631 FindKeywordPackages = TRUE;\r
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
2646\r
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
2661\r
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
2695\r
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
2718 }\r
2719 }\r
2720\r
2721 if (LocalNameSpace != NULL) {\r
2722 FreePool (LocalNameSpace);\r
2723 LocalNameSpace = NULL;\r
2724 }\r
2725 }\r
2726 }\r
2727 }\r
2728\r
2729 //\r
2730 // return the already get MultiKeywordString even error occurred.\r
2731 //\r
2732 if (MultiKeywordResp == NULL) {\r
2733 Status = EFI_NOT_FOUND;\r
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
2739 } else {\r
2740 Status = EFI_SUCCESS;\r
2741 }\r
2742 *MultiResp = MultiKeywordResp;\r
2743\r
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
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
2766 appropriate information about where the issue occurred and additional data about\r
2767 the nature of the issue.\r
2768\r
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
2771 storage associated with earlier keywords is not modified. All elements of the\r
2772 KeywordString must successfully pass all tests for format and access prior to making\r
2773 any modifications to storage.\r
2774\r
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
2782 @param KeywordString A null-terminated string in <MultiKeywordResp> format.\r
2783\r
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
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
2790\r
2791 @param ProgressErr If during the processing of the KeywordString there was\r
2792 a failure, this parameter gives additional information\r
2793 about the possible source of the problem. The various\r
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
2801 2. Parsing of the KeywordString resulted in an\r
2802 error. See Progress and ProgressErr for more data.\r
2803\r
2804 @retval EFI_NOT_FOUND An element of the KeywordString was not found.\r
2805 See ProgressErr for more data.\r
2806\r
2807 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
2808 See ProgressErr for more data.\r
2809\r
2810 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr\r
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
2818EFIAPI\r
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
2830 CHAR16 *NextStringPtr;\r
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
2841 CHAR16 *TempString;\r
2842 CHAR16 *KeywordStartPos;\r
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
2851 MultiConfigResp = NULL;\r
2852 NameSpace = NULL;\r
2853 DevicePath = NULL;\r
2854 KeywordData = NULL;\r
2855 ValueElement = NULL;\r
2856 ConfigResp = NULL;\r
2857 KeywordStartPos = NULL;\r
2858 KeywordStringId = 0;\r
2859\r
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
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
2874 goto Done;\r
2875 }\r
2876 ASSERT (NameSpace != NULL);\r
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
2881 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
2882 Status = EFI_INVALID_PARAMETER;\r
2883 goto Done;\r
2884 }\r
2885\r
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
2901 KeywordStartPos = StringPtr;\r
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
2928 // 5. Find READONLY tag.\r
2929 //\r
2930 if ((StringPtr != NULL) && StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0) {\r
2931 ReadOnly = TRUE;\r
2932 StringPtr += StrLen (L"&READONLY");\r
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
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
2967 *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;\r
2968 Status = EFI_ACCESS_DENIED;\r
2969 goto Done;\r
2970 }\r
2971\r
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
2988 DevicePath = NULL;\r
2989 KeywordData = NULL;\r
2990 ValueElement = NULL;\r
2991 if (ConfigResp != NULL) {\r
2992 FreePool (ConfigResp);\r
2993 ConfigResp = NULL;\r
2994 }\r
2995 KeywordStartPos = NULL;\r
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
3010\r
3011 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
3012\r
3013Done:\r
3014 if (KeywordStartPos != NULL) {\r
3015 *Progress = KeywordString + (KeywordStartPos - TempString);\r
3016 } else {\r
3017 *Progress = KeywordString + (StringPtr - TempString);\r
3018 }\r
3019\r
3020 ASSERT (TempString != NULL);\r
3021 FreePool (TempString);\r
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
3039 }\r
3040\r
3041 return Status;\r
3042}\r
3043\r
3044/**\r
3045\r
3046 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying\r
3047 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the\r
3048 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.\r
3049\r
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
3054\r
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
3057 contains values returned for all keywords processed prior to the keyword generating the\r
3058 error but no values for the keyword with error or any following keywords.\r
3059\r
3060\r
3061 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
3062\r
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
3067\r
3068 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a\r
3069 NULL is passed in the KeywordString field, all of the known\r
3070 keywords in the system for the NameSpaceId specified are\r
3071 returned in the Results field.\r
3072\r
3073 @param Progress On return, points to a character in the KeywordString. Points\r
3074 to the string's NULL terminator if the request was successful.\r
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
3078\r
3079 @param ProgressErr If during the processing of the KeywordString there was a\r
3080 failure, this parameter gives additional information about the\r
3081 possible source of the problem. See the definitions in SetData()\r
3082 for valid value definitions.\r
3083\r
3084 @param Results A null-terminated string in <MultiKeywordResp> format is returned\r
3085 which has all the values filled in for the keywords in the\r
3086 KeywordString. This is a callee-allocated field, and must be freed\r
3087 by the caller after being used.\r
3088\r
3089 @retval EFI_SUCCESS The specified action was completed successfully.\r
3090\r
3091 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
3092 1.Progress, ProgressErr, or Results is NULL.\r
3093 2.Parsing of the KeywordString resulted in an error. See\r
3094 Progress and ProgressErr for more data.\r
3095\r
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
3105\r
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
3114EFIAPI\r
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
3119 OUT EFI_STRING *Progress,\r
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
3129 CHAR16 *NextStringPtr;\r
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
3139 CHAR16 *TempString;\r
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
3155 TempString = NULL;\r
3156\r
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
3164 //\r
3165 // 1. Get NameSpace from NameSpaceId keyword.\r
3166 //\r
3167 Status = ExtractNameSpace (TempString, &NameSpace, NULL);\r
3168 if (TempString != NULL) {\r
3169 FreePool (TempString);\r
3170 TempString = NULL;\r
3171 }\r
3172 if (EFI_ERROR (Status)) {\r
3173 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
3174 return Status;\r
3175 }\r
3176 //\r
3177 // 1.1 Check whether the input namespace is valid.\r
3178 //\r
3179 if (NameSpace != NULL){\r
3180 if (AsciiStrnCmp(NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {\r
3181 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
3182 return EFI_INVALID_PARAMETER;\r
3183 }\r
3184 }\r
3185\r
3186 if (KeywordString != NULL) {\r
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
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
3205\r
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
3237\r
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
3290 DevicePath = NULL;\r
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
3303 Status = EnumerateAllKeywords(NameSpace, &MultiKeywordResp, ProgressErr);\r
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
3313 *Progress = KeywordString + (StringPtr - TempString);\r
3314\r
3315 if (TempString != NULL) {\r
3316 FreePool (TempString);\r
3317 }\r
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
3327\r
3328 return Status;\r
3329}\r