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