TianoCore EDK2 master
Loading...
Searching...
No Matches
ConfigKeywordHandler.c
Go to the documentation of this file.
1
9#include "HiiDatabase.h"
10
11extern HII_DATABASE_PRIVATE_DATA mPrivate;
12
31 IN EFI_STRING String,
32 OUT UINT8 **DevicePathData,
33 OUT EFI_STRING *NextString
34 )
35{
36 UINTN Length;
37 EFI_STRING PathHdr;
38 UINT8 *DevicePathBuffer;
39 CHAR16 TemStr[2];
40 UINTN Index;
41 UINT8 DigitUint8;
42 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
43
44 ASSERT (NextString != NULL && DevicePathData != NULL);
45
46 //
47 // KeywordRequest == NULL case.
48 //
49 if (String == NULL) {
50 *DevicePathData = NULL;
51 *NextString = NULL;
52 return EFI_SUCCESS;
53 }
54
55 //
56 // Skip '&' if exist.
57 //
58 if (*String == L'&') {
59 String++;
60 }
61
62 //
63 // Find the 'PATH=' of <PathHdr>.
64 //
65 if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {
66 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
67 return EFI_INVALID_PARAMETER;
68 } else {
69 //
70 // Not include PathHdr, return success and DevicePath = NULL.
71 //
72 *DevicePathData = NULL;
73 *NextString = String;
74 return EFI_SUCCESS;
75 }
76 }
77
78 //
79 // Check whether path data does exist.
80 //
81 String += StrLen (L"PATH=");
82 if (*String == 0) {
83 return EFI_INVALID_PARAMETER;
84 }
85
86 PathHdr = String;
87
88 //
89 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
90 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
91 // of UEFI device path.
92 //
93 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {
94 }
95
96 //
97 // Save the return next keyword string value.
98 //
99 *NextString = String;
100
101 //
102 // Check DevicePath Length
103 //
104 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 //
109 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
110 // as the device path resides in RAM memory.
111 // Translate the data into binary.
112 //
113 DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);
114 if (DevicePathBuffer == NULL) {
115 return EFI_OUT_OF_RESOURCES;
116 }
117
118 //
119 // Convert DevicePath
120 //
121 ZeroMem (TemStr, sizeof (TemStr));
122 for (Index = 0; Index < Length; Index++) {
123 TemStr[0] = PathHdr[Index];
124 DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
125 if ((Index & 1) == 0) {
126 DevicePathBuffer[Index/2] = DigitUint8;
127 } else {
128 DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);
129 }
130 }
131
132 //
133 // Validate DevicePath
134 //
135 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;
136 while (!IsDevicePathEnd (DevicePath)) {
137 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
138 //
139 // Invalid device path
140 //
141 FreePool (DevicePathBuffer);
142 return EFI_INVALID_PARAMETER;
143 }
144
145 DevicePath = NextDevicePathNode (DevicePath);
146 }
147
148 //
149 // return the device path
150 //
151 *DevicePathData = DevicePathBuffer;
152
153 return EFI_SUCCESS;
154}
155
171 IN EFI_STRING String,
172 OUT CHAR8 **NameSpace,
173 OUT EFI_STRING *NextString
174 )
175{
176 CHAR16 *TmpPtr;
177 UINTN NameSpaceSize;
178
179 ASSERT (NameSpace != NULL);
180
181 TmpPtr = NULL;
182
183 //
184 // Input NameSpaceId == NULL
185 //
186 if (String == NULL) {
187 *NameSpace = NULL;
188 if (NextString != NULL) {
189 *NextString = NULL;
190 }
191
192 return EFI_SUCCESS;
193 }
194
195 //
196 // Skip '&' if exist.
197 //
198 if (*String == L'&') {
199 String++;
200 }
201
202 if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {
203 return EFI_INVALID_PARAMETER;
204 }
205
206 String += StrLen (L"NAMESPACE=");
207
208 TmpPtr = StrStr (String, L"&");
209 if (TmpPtr != NULL) {
210 *TmpPtr = 0;
211 }
212
213 if (NextString != NULL) {
214 *NextString = String + StrLen (String);
215 }
216
217 //
218 // Input NameSpace is unicode string. The language in String package is ascii string.
219 // Here will convert the unicode string to ascii and save it.
220 //
221 NameSpaceSize = StrLen (String) + 1;
222 *NameSpace = AllocatePool (NameSpaceSize);
223 if (*NameSpace == NULL) {
224 return EFI_OUT_OF_RESOURCES;
225 }
226
227 UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);
228
229 if (TmpPtr != NULL) {
230 *TmpPtr = L'&';
231 }
232
233 return EFI_SUCCESS;
234}
235
251 IN EFI_STRING String,
252 OUT EFI_STRING *Keyword,
253 OUT EFI_STRING *NextString
254 )
255{
256 EFI_STRING TmpPtr;
257
258 ASSERT ((Keyword != NULL) && (NextString != NULL));
259
260 TmpPtr = NULL;
261
262 //
263 // KeywordRequest == NULL case.
264 //
265 if (String == NULL) {
266 *Keyword = NULL;
267 *NextString = NULL;
268 return EFI_SUCCESS;
269 }
270
271 //
272 // Skip '&' if exist.
273 //
274 if (*String == L'&') {
275 String++;
276 }
277
278 if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
279 return EFI_INVALID_PARAMETER;
280 }
281
282 String += StrLen (L"KEYWORD=");
283
284 TmpPtr = StrStr (String, L"&");
285 if (TmpPtr != NULL) {
286 *TmpPtr = 0;
287 }
288
289 *NextString = String + StrLen (String);
290
291 *Keyword = AllocateCopyPool (StrSize (String), String);
292 if (*Keyword == NULL) {
293 return EFI_OUT_OF_RESOURCES;
294 }
295
296 if (TmpPtr != NULL) {
297 *TmpPtr = L'&';
298 }
299
300 return EFI_SUCCESS;
301}
302
318 IN EFI_STRING String,
319 OUT EFI_STRING *Value,
320 OUT EFI_STRING *NextString
321 )
322{
323 EFI_STRING TmpPtr;
324
325 ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));
326
327 //
328 // Skip '&' if exist.
329 //
330 if (*String == L'&') {
331 String++;
332 }
333
334 if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {
335 return EFI_INVALID_PARAMETER;
336 }
337
338 String += StrLen (L"VALUE=");
339
340 TmpPtr = StrStr (String, L"&");
341 if (TmpPtr != NULL) {
342 *TmpPtr = 0;
343 }
344
345 *NextString = String + StrLen (String);
346
347 *Value = AllocateCopyPool (StrSize (String), String);
348 if (*Value == NULL) {
349 return EFI_OUT_OF_RESOURCES;
350 }
351
352 if (TmpPtr != NULL) {
353 *TmpPtr = L'&';
354 }
355
356 return EFI_SUCCESS;
357}
358
372BOOLEAN
374 IN EFI_STRING String,
375 OUT UINT8 *FilterFlags,
376 OUT EFI_STRING *NextString
377 )
378{
379 CHAR16 *PathPtr;
380 CHAR16 *KeywordPtr;
381 BOOLEAN RetVal;
382
383 ASSERT ((FilterFlags != NULL) && (NextString != NULL));
384
385 //
386 // String end, no filter section.
387 //
388 if (String == NULL) {
389 *NextString = NULL;
390 return FALSE;
391 }
392
393 *FilterFlags = 0;
394 RetVal = TRUE;
395
396 //
397 // Skip '&' if exist.
398 //
399 if (*String == L'&') {
400 String++;
401 }
402
403 if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {
404 //
405 // Find ReadOnly filter.
406 //
407 *FilterFlags |= EFI_KEYWORD_FILTER_READONY;
408 String += StrLen (L"ReadOnly");
409 } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {
410 //
411 // Find ReadWrite filter.
412 //
413 *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;
414 String += StrLen (L"ReadWrite");
415 } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {
416 //
417 // Find Buffer Filter.
418 //
419 *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;
420 String += StrLen (L"Buffer");
421 } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {
422 //
423 // Find Numeric Filter
424 //
425 String += StrLen (L"Numeric");
426 if (*String != L':') {
427 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;
428 } else {
429 String++;
430 switch (*String) {
431 case L'1':
432 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;
433 break;
434 case L'2':
435 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;
436 break;
437 case L'4':
438 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;
439 break;
440 case L'8':
441 *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;
442 break;
443 default:
444 ASSERT (FALSE);
445 break;
446 }
447
448 String++;
449 }
450 } else {
451 //
452 // Check whether other filter item defined by Platform.
453 //
454 if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||
455 (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0))
456 {
457 //
458 // New KeywordRequest start, no platform defined filter.
459 //
460 } else {
461 //
462 // Platform defined filter rule.
463 // Just skip platform defined filter rule, return success.
464 //
465 PathPtr = StrStr (String, L"&PATH");
466 KeywordPtr = StrStr (String, L"&KEYWORD");
467 if ((PathPtr != NULL) && (KeywordPtr != NULL)) {
468 //
469 // If both sections exist, return the first follow string.
470 //
471 String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;
472 } else if (PathPtr != NULL) {
473 //
474 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
475 //
476 ASSERT (FALSE);
477 } else if (KeywordPtr != NULL) {
478 //
479 // Just to the next keyword section.
480 //
481 String = KeywordPtr;
482 } else {
483 //
484 // Only has platform defined filter section, just skip it.
485 //
486 String += StrLen (String);
487 }
488 }
489
490 RetVal = FALSE;
491 }
492
493 *NextString = String;
494
495 return RetVal;
496}
497
509BOOLEAN
511 IN UINT8 *OpCodeData
512 )
513{
514 EFI_IFR_QUESTION_HEADER *QuestionHdr;
515
516 ASSERT (OpCodeData != NULL);
517
518 QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
519
520 return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;
521}
522
537UINT32
539 IN UINT8 *OpCodeData,
540 IN CHAR16 *KeywordRequest,
541 OUT CHAR16 **NextString,
542 OUT BOOLEAN *ReadOnly
543 )
544{
545 CHAR16 *NextFilter;
546 CHAR16 *StringPtr;
547 UINT8 FilterFlags;
548 EFI_IFR_QUESTION_HEADER *QuestionHdr;
549 EFI_IFR_OP_HEADER *OpCodeHdr;
550 UINT8 Flags;
551 UINT32 RetVal;
552
553 RetVal = KEYWORD_HANDLER_NO_ERROR;
554 StringPtr = KeywordRequest;
555
556 OpCodeHdr = (EFI_IFR_OP_HEADER *)OpCodeData;
557 QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
558 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
559 Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));
560 } else {
561 Flags = 0;
562 }
563
564 //
565 // Get ReadOnly flag from Question.
566 //
567 *ReadOnly = ExtractReadOnlyFromOpCode (OpCodeData);
568
569 while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {
570 switch (FilterFlags) {
571 case EFI_KEYWORD_FILTER_READONY:
572 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {
573 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
574 goto Done;
575 }
576
577 break;
578
579 case EFI_KEYWORD_FILTER_REAWRITE:
580 if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {
581 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
582 goto Done;
583 }
584
585 break;
586
587 case EFI_KEYWORD_FILTER_BUFFER:
588 //
589 // Only these three opcode use numeric value type.
590 //
591 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) || (OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP)) {
592 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
593 goto Done;
594 }
595
596 break;
597
598 case EFI_KEYWORD_FILTER_NUMERIC:
599 if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
600 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
601 goto Done;
602 }
603
604 break;
605
606 case EFI_KEYWORD_FILTER_NUMERIC_1:
607 case EFI_KEYWORD_FILTER_NUMERIC_2:
608 case EFI_KEYWORD_FILTER_NUMERIC_4:
609 case EFI_KEYWORD_FILTER_NUMERIC_8:
610 if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
611 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
612 goto Done;
613 }
614
615 //
616 // For numeric and oneof, it has flags field to specify the detail numeric type.
617 //
618 if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
619 switch (Flags & EFI_IFR_NUMERIC_SIZE) {
620 case EFI_IFR_NUMERIC_SIZE_1:
621 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {
622 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
623 goto Done;
624 }
625
626 break;
627
628 case EFI_IFR_NUMERIC_SIZE_2:
629 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {
630 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
631 goto Done;
632 }
633
634 break;
635
636 case EFI_IFR_NUMERIC_SIZE_4:
637 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {
638 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
639 goto Done;
640 }
641
642 break;
643
644 case EFI_IFR_NUMERIC_SIZE_8:
645 if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {
646 RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
647 goto Done;
648 }
649
650 break;
651
652 default:
653 ASSERT (FALSE);
654 break;
655 }
656 }
657
658 break;
659
660 default:
661 ASSERT (FALSE);
662 break;
663 }
664
665 //
666 // Jump to the next filter.
667 //
668 StringPtr = NextFilter;
669 }
670
671Done:
672 //
673 // The current filter which is processing.
674 //
675 *NextString = StringPtr;
676
677 return RetVal;
678}
679
692 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
693 )
694{
695 LIST_ENTRY *Link;
696 UINT8 *DevicePathPkg;
697 UINT8 *CurrentDevicePath;
698 UINTN DevicePathSize;
699 HII_DATABASE_RECORD *TempDatabase;
700
701 ASSERT (DevicePath != NULL);
702
703 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
704 TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
705 DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;
706 if (DevicePathPkg != NULL) {
707 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
708 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
709 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {
710 return TempDatabase;
711 }
712 }
713 }
714
715 return NULL;
716}
717
734 IN UINT8 *StringSrc,
735 OUT UINTN *BufferSize,
736 OUT EFI_STRING *StringDest
737 )
738{
739 UINTN StringSize;
740 UINT8 *StringPtr;
741
742 ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);
743
744 StringSize = sizeof (CHAR16);
745 StringPtr = StringSrc;
746 while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
747 StringSize += sizeof (CHAR16);
748 StringPtr += sizeof (CHAR16);
749 }
750
751 *StringDest = AllocatePool (StringSize);
752 if (*StringDest == NULL) {
753 return EFI_OUT_OF_RESOURCES;
754 }
755
756 CopyMem (*StringDest, StringSrc, StringSize);
757
758 *BufferSize = StringSize;
759 return EFI_SUCCESS;
760}
761
779 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
780 IN CHAR16 *KeywordValue,
781 OUT EFI_STRING_ID *StringId
782 )
783{
784 UINT8 *BlockHdr;
785 EFI_STRING_ID CurrentStringId;
786 UINTN BlockSize;
787 UINTN Index;
788 UINT8 *StringTextPtr;
789 UINTN Offset;
790 UINT16 StringCount;
791 UINT16 SkipCount;
792 UINT8 Length8;
794 UINT32 Length32;
795 UINTN StringSize;
796 CHAR16 *String;
797 CHAR8 *AsciiKeywordValue;
798 UINTN KeywordValueSize;
799 EFI_STATUS Status;
800
801 ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);
802 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
803
804 CurrentStringId = 1;
805 Status = EFI_SUCCESS;
806 String = NULL;
807 BlockHdr = StringPackage->StringBlock;
808 BlockSize = 0;
809 Offset = 0;
810
811 //
812 // Make a ascii keyword value for later use.
813 //
814 KeywordValueSize = StrLen (KeywordValue) + 1;
815 AsciiKeywordValue = AllocatePool (KeywordValueSize);
816 if (AsciiKeywordValue == NULL) {
817 return EFI_OUT_OF_RESOURCES;
818 }
819
820 UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);
821
822 while (*BlockHdr != EFI_HII_SIBT_END) {
823 switch (*BlockHdr) {
824 case EFI_HII_SIBT_STRING_SCSU:
825 Offset = sizeof (EFI_HII_STRING_BLOCK);
826 StringTextPtr = BlockHdr + Offset;
827 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
828 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
829 *StringId = CurrentStringId;
830 goto Done;
831 }
832
833 CurrentStringId++;
834 break;
835
836 case EFI_HII_SIBT_STRING_SCSU_FONT:
837 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
838 StringTextPtr = BlockHdr + Offset;
839 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
840 *StringId = CurrentStringId;
841 goto Done;
842 }
843
844 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
845 CurrentStringId++;
846 break;
847
848 case EFI_HII_SIBT_STRINGS_SCSU:
849 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
850 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
851 BlockSize += StringTextPtr - BlockHdr;
852
853 for (Index = 0; Index < StringCount; Index++) {
854 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
855 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
856 *StringId = CurrentStringId;
857 goto Done;
858 }
859
860 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
861 CurrentStringId++;
862 }
863
864 break;
865
866 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
867 CopyMem (
868 &StringCount,
869 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
870 sizeof (UINT16)
871 );
872 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
873 BlockSize += StringTextPtr - BlockHdr;
874
875 for (Index = 0; Index < StringCount; Index++) {
876 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
877 if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
878 *StringId = CurrentStringId;
879 goto Done;
880 }
881
882 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
883 CurrentStringId++;
884 }
885
886 break;
887
888 case EFI_HII_SIBT_STRING_UCS2:
889 Offset = sizeof (EFI_HII_STRING_BLOCK);
890 StringTextPtr = BlockHdr + Offset;
891 //
892 // Use StringSize to store the size of the specified string, including the NULL
893 // terminator.
894 //
895 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
896 if (EFI_ERROR (Status)) {
897 goto Done;
898 }
899
900 ASSERT (String != NULL);
901 if (StrCmp (KeywordValue, String) == 0) {
902 *StringId = CurrentStringId;
903 goto Done;
904 }
905
906 BlockSize += Offset + StringSize;
907 CurrentStringId++;
908 break;
909
910 case EFI_HII_SIBT_STRING_UCS2_FONT:
911 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
912 StringTextPtr = BlockHdr + Offset;
913 //
914 // Use StringSize to store the size of the specified string, including the NULL
915 // terminator.
916 //
917 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
918 if (EFI_ERROR (Status)) {
919 goto Done;
920 }
921
922 ASSERT (String != NULL);
923 if (StrCmp (KeywordValue, String) == 0) {
924 *StringId = CurrentStringId;
925 goto Done;
926 }
927
928 BlockSize += Offset + StringSize;
929 CurrentStringId++;
930 break;
931
932 case EFI_HII_SIBT_STRINGS_UCS2:
933 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
934 StringTextPtr = BlockHdr + Offset;
935 BlockSize += Offset;
936 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
937 for (Index = 0; Index < StringCount; Index++) {
938 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
939 if (EFI_ERROR (Status)) {
940 goto Done;
941 }
942
943 ASSERT (String != NULL);
944 BlockSize += StringSize;
945 if (StrCmp (KeywordValue, String) == 0) {
946 *StringId = CurrentStringId;
947 goto Done;
948 }
949
950 StringTextPtr = StringTextPtr + StringSize;
951 CurrentStringId++;
952 }
953
954 break;
955
956 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
957 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
958 StringTextPtr = BlockHdr + Offset;
959 BlockSize += Offset;
960 CopyMem (
961 &StringCount,
962 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
963 sizeof (UINT16)
964 );
965 for (Index = 0; Index < StringCount; Index++) {
966 Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
967 if (EFI_ERROR (Status)) {
968 goto Done;
969 }
970
971 ASSERT (String != NULL);
972 BlockSize += StringSize;
973 if (StrCmp (KeywordValue, String) == 0) {
974 *StringId = CurrentStringId;
975 goto Done;
976 }
977
978 StringTextPtr = StringTextPtr + StringSize;
979 CurrentStringId++;
980 }
981
982 break;
983
984 case EFI_HII_SIBT_DUPLICATE:
985 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
986 CurrentStringId++;
987 break;
988
989 case EFI_HII_SIBT_SKIP1:
990 SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
991 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
992 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
993 break;
994
995 case EFI_HII_SIBT_SKIP2:
996 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
997 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
998 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
999 break;
1000
1001 case EFI_HII_SIBT_EXT1:
1002 CopyMem (
1003 &Length8,
1004 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1005 sizeof (UINT8)
1006 );
1007 BlockSize += Length8;
1008 break;
1009
1010 case EFI_HII_SIBT_EXT2:
1011 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1012 BlockSize += Ext2.Length;
1013 break;
1014
1015 case EFI_HII_SIBT_EXT4:
1016 CopyMem (
1017 &Length32,
1018 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1019 sizeof (UINT32)
1020 );
1021
1022 BlockSize += Length32;
1023 break;
1024
1025 default:
1026 break;
1027 }
1028
1029 if (String != NULL) {
1030 FreePool (String);
1031 String = NULL;
1032 }
1033
1034 BlockHdr = StringPackage->StringBlock + BlockSize;
1035 }
1036
1037 Status = EFI_NOT_FOUND;
1038
1039Done:
1040 if (AsciiKeywordValue != NULL) {
1041 FreePool (AsciiKeywordValue);
1042 }
1043
1044 if (String != NULL) {
1045 FreePool (String);
1046 }
1047
1048 return Status;
1049}
1050
1063EFI_STRING_ID
1065 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
1066 IN EFI_STRING_ID StringId,
1067 OUT EFI_STRING *KeywordValue
1068 )
1069{
1070 UINT8 *BlockHdr;
1071 EFI_STRING_ID CurrentStringId;
1072 UINTN BlockSize;
1073 UINTN Index;
1074 UINT8 *StringTextPtr;
1075 UINTN Offset;
1076 UINT16 StringCount;
1077 UINT16 SkipCount;
1078 UINT8 Length8;
1080 UINT32 Length32;
1081 BOOLEAN FindString;
1082 UINTN StringSize;
1083 CHAR16 *String;
1084
1085 ASSERT (StringPackage != NULL);
1086 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
1087
1088 CurrentStringId = 1;
1089 FindString = FALSE;
1090 String = NULL;
1091
1092 //
1093 // Parse the string blocks to get the string text and font.
1094 //
1095 BlockHdr = StringPackage->StringBlock;
1096 BlockSize = 0;
1097 Offset = 0;
1098 while (*BlockHdr != EFI_HII_SIBT_END) {
1099 switch (*BlockHdr) {
1100 case EFI_HII_SIBT_STRING_SCSU:
1101 Offset = sizeof (EFI_HII_STRING_BLOCK);
1102 StringTextPtr = BlockHdr + Offset;
1103
1104 if (FindString) {
1105 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
1106 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
1107 if (*KeywordValue == NULL) {
1108 return 0;
1109 }
1110
1111 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
1112 return CurrentStringId;
1113 } else if (CurrentStringId == StringId) {
1114 FindString = TRUE;
1115 }
1116
1117 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
1118 CurrentStringId++;
1119 break;
1120
1121 case EFI_HII_SIBT_STRING_SCSU_FONT:
1122 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
1123 StringTextPtr = BlockHdr + Offset;
1124
1125 if (FindString) {
1126 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
1127 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
1128 if (*KeywordValue == NULL) {
1129 return 0;
1130 }
1131
1132 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
1133 return CurrentStringId;
1134 } else if (CurrentStringId == StringId) {
1135 FindString = TRUE;
1136 }
1137
1138 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
1139 CurrentStringId++;
1140 break;
1141
1142 case EFI_HII_SIBT_STRINGS_SCSU:
1143 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1144 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
1145 BlockSize += StringTextPtr - BlockHdr;
1146
1147 for (Index = 0; Index < StringCount; Index++) {
1148 if (FindString) {
1149 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
1150 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
1151 if (*KeywordValue == NULL) {
1152 return 0;
1153 }
1154
1155 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
1156 return CurrentStringId;
1157 } else if (CurrentStringId == StringId) {
1158 FindString = TRUE;
1159 }
1160
1161 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
1162 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
1163 CurrentStringId++;
1164 }
1165
1166 break;
1167
1168 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
1169 CopyMem (
1170 &StringCount,
1171 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1172 sizeof (UINT16)
1173 );
1174 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
1175 BlockSize += StringTextPtr - BlockHdr;
1176
1177 for (Index = 0; Index < StringCount; Index++) {
1178 if (FindString) {
1179 StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
1180 *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
1181 if (*KeywordValue == NULL) {
1182 return 0;
1183 }
1184
1185 AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
1186 return CurrentStringId;
1187 } else if (CurrentStringId == StringId) {
1188 FindString = TRUE;
1189 }
1190
1191 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
1192 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
1193 CurrentStringId++;
1194 }
1195
1196 break;
1197
1198 case EFI_HII_SIBT_STRING_UCS2:
1199 Offset = sizeof (EFI_HII_STRING_BLOCK);
1200 StringTextPtr = BlockHdr + Offset;
1201 //
1202 // Use StringSize to store the size of the specified string, including the NULL
1203 // terminator.
1204 //
1205 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
1206 if (FindString && (String != NULL) && (*String != L'\0')) {
1207 //
1208 // String protocol use this type for the string id which has value for other package.
1209 // It will allocate an empty string block for this string id. so here we also check
1210 // *String != L'\0' to prohibit this case.
1211 //
1212 *KeywordValue = String;
1213 return CurrentStringId;
1214 } else if (CurrentStringId == StringId) {
1215 FindString = TRUE;
1216 }
1217
1218 BlockSize += Offset + StringSize;
1219 CurrentStringId++;
1220 break;
1221
1222 case EFI_HII_SIBT_STRING_UCS2_FONT:
1223 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
1224 StringTextPtr = BlockHdr + Offset;
1225 //
1226 // Use StringSize to store the size of the specified string, including the NULL
1227 // terminator.
1228 //
1229 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
1230 if (FindString) {
1231 *KeywordValue = String;
1232 return CurrentStringId;
1233 } else if (CurrentStringId == StringId) {
1234 FindString = TRUE;
1235 }
1236
1237 BlockSize += Offset + StringSize;
1238 CurrentStringId++;
1239 break;
1240
1241 case EFI_HII_SIBT_STRINGS_UCS2:
1242 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
1243 StringTextPtr = BlockHdr + Offset;
1244 BlockSize += Offset;
1245 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1246 for (Index = 0; Index < StringCount; Index++) {
1247 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
1248
1249 if (FindString) {
1250 *KeywordValue = String;
1251 return CurrentStringId;
1252 } else if (CurrentStringId == StringId) {
1253 FindString = TRUE;
1254 }
1255
1256 BlockSize += StringSize;
1257 StringTextPtr = StringTextPtr + StringSize;
1258 CurrentStringId++;
1259 }
1260
1261 break;
1262
1263 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
1264 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
1265 StringTextPtr = BlockHdr + Offset;
1266 BlockSize += Offset;
1267 CopyMem (
1268 &StringCount,
1269 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1270 sizeof (UINT16)
1271 );
1272 for (Index = 0; Index < StringCount; Index++) {
1273 GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
1274 if (FindString) {
1275 *KeywordValue = String;
1276 return CurrentStringId;
1277 } else if (CurrentStringId == StringId) {
1278 FindString = TRUE;
1279 }
1280
1281 BlockSize += StringSize;
1282 StringTextPtr = StringTextPtr + StringSize;
1283 CurrentStringId++;
1284 }
1285
1286 break;
1287
1288 case EFI_HII_SIBT_DUPLICATE:
1289 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
1290 CurrentStringId++;
1291 break;
1292
1293 case EFI_HII_SIBT_SKIP1:
1294 SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
1295 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
1296 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
1297 break;
1298
1299 case EFI_HII_SIBT_SKIP2:
1300 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1301 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
1302 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1303 break;
1304
1305 case EFI_HII_SIBT_EXT1:
1306 CopyMem (
1307 &Length8,
1308 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1309 sizeof (UINT8)
1310 );
1311 BlockSize += Length8;
1312 break;
1313
1314 case EFI_HII_SIBT_EXT2:
1315 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1316 BlockSize += Ext2.Length;
1317 break;
1318
1319 case EFI_HII_SIBT_EXT4:
1320 CopyMem (
1321 &Length32,
1322 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1323 sizeof (UINT32)
1324 );
1325
1326 BlockSize += Length32;
1327 break;
1328
1329 default:
1330 break;
1331 }
1332
1333 if (String != NULL) {
1334 FreePool (String);
1335 String = NULL;
1336 }
1337
1338 BlockHdr = StringPackage->StringBlock + BlockSize;
1339 }
1340
1341 return 0;
1342}
1343
1360UINT32
1362 IN HII_DATABASE_RECORD *DatabaseRecord,
1363 IN CHAR8 **NameSpace,
1364 IN CHAR16 *KeywordValue,
1365 OUT EFI_STRING_ID *StringId
1366 )
1367{
1368 LIST_ENTRY *Link;
1369 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1370 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1371 EFI_STATUS Status;
1372 CHAR8 *Name;
1373 UINT32 RetVal;
1374
1375 ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);
1376
1377 PackageListNode = DatabaseRecord->PackageList;
1378 RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
1379
1380 if (*NameSpace != NULL) {
1381 Name = *NameSpace;
1382 } else {
1383 Name = UEFI_CONFIG_LANG;
1384 }
1385
1386 for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {
1387 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1388
1389 if (AsciiStrnCmp (Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {
1390 Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);
1391 if (EFI_ERROR (Status)) {
1392 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
1393 } else {
1394 if (*NameSpace == NULL) {
1395 *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
1396 if (*NameSpace == NULL) {
1397 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
1398 }
1399 }
1400
1401 return KEYWORD_HANDLER_NO_ERROR;
1402 }
1403 }
1404 }
1405
1406 return RetVal;
1407}
1408
1418BOOLEAN
1420 IN UINT8 Operand
1421 )
1422{
1423 if ((Operand == EFI_IFR_SUBTITLE_OP) ||
1424 (Operand == EFI_IFR_TEXT_OP) ||
1425 (Operand == EFI_IFR_RESET_BUTTON_OP) ||
1426 (Operand == EFI_IFR_REF_OP) ||
1427 (Operand == EFI_IFR_ACTION_OP) ||
1428 (Operand == EFI_IFR_NUMERIC_OP) ||
1429 (Operand == EFI_IFR_ORDERED_LIST_OP) ||
1430 (Operand == EFI_IFR_CHECKBOX_OP) ||
1431 (Operand == EFI_IFR_STRING_OP) ||
1432 (Operand == EFI_IFR_PASSWORD_OP) ||
1433 (Operand == EFI_IFR_DATE_OP) ||
1434 (Operand == EFI_IFR_TIME_OP) ||
1435 (Operand == EFI_IFR_GUID_OP) ||
1436 (Operand == EFI_IFR_ONE_OF_OP))
1437 {
1438 return TRUE;
1439 }
1440
1441 return FALSE;
1442}
1443
1453BOOLEAN
1455 IN UINT8 Operand
1456 )
1457{
1458 if ((Operand == EFI_IFR_VARSTORE_OP) ||
1459 (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
1460 (Operand == EFI_IFR_VARSTORE_EFI_OP))
1461 {
1462 return TRUE;
1463 }
1464
1465 return FALSE;
1466}
1467
1477UINT8 *
1479 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
1480 IN EFI_STRING_ID KeywordStrId
1481 )
1482{
1483 UINT8 *OpCodeData;
1484 UINT32 Offset;
1485 EFI_IFR_STATEMENT_HEADER *StatementHeader;
1486 EFI_IFR_OP_HEADER *OpCodeHeader;
1487 UINT32 FormDataLen;
1488
1489 ASSERT (FormPackage != NULL);
1490
1491 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
1492 Offset = 0;
1493 while (Offset < FormDataLen) {
1494 OpCodeData = FormPackage->IfrData + Offset;
1495 OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
1496
1497 if (IsStatementOpCode (OpCodeHeader->OpCode)) {
1498 StatementHeader = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
1499 if (StatementHeader->Prompt == KeywordStrId) {
1500 return OpCodeData;
1501 }
1502 }
1503
1504 Offset += OpCodeHeader->Length;
1505 }
1506
1507 return NULL;
1508}
1509
1519UINT8 *
1521 IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
1522 IN EFI_VARSTORE_ID VarStoreId
1523 )
1524{
1525 UINT8 *OpCodeData;
1526 UINT32 Offset;
1527 EFI_IFR_OP_HEADER *OpCodeHeader;
1528 UINT32 FormDataLen;
1529
1530 ASSERT (FormPackage != NULL);
1531
1532 FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
1533 Offset = 0;
1534 while (Offset < FormDataLen) {
1535 OpCodeData = FormPackage->IfrData + Offset;
1536 OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
1537
1538 if (IsStorageOpCode (OpCodeHeader->OpCode)) {
1539 switch (OpCodeHeader->OpCode) {
1540 case EFI_IFR_VARSTORE_OP:
1541 if (VarStoreId == ((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId) {
1542 return OpCodeData;
1543 }
1544
1545 break;
1546
1547 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1548 if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId) {
1549 return OpCodeData;
1550 }
1551
1552 break;
1553
1554 case EFI_IFR_VARSTORE_EFI_OP:
1555 if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId) {
1556 return OpCodeData;
1557 }
1558
1559 break;
1560
1561 default:
1562 break;
1563 }
1564 }
1565
1566 Offset += OpCodeHeader->Length;
1567 }
1568
1569 return NULL;
1570}
1571
1580UINT16
1582 IN UINT8 *OpCodeData
1583 )
1584{
1585 UINT8 *NextOpCodeData;
1586
1587 ASSERT (OpCodeData != NULL);
1588
1589 switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
1590 case EFI_IFR_REF_OP:
1591 return (UINT16)sizeof (EFI_HII_REF);
1592
1593 case EFI_IFR_ONE_OF_OP:
1594 case EFI_IFR_NUMERIC_OP:
1595 switch (((EFI_IFR_ONE_OF *)OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {
1596 case EFI_IFR_NUMERIC_SIZE_1:
1597 return (UINT16)sizeof (UINT8);
1598
1599 case EFI_IFR_NUMERIC_SIZE_2:
1600 return (UINT16)sizeof (UINT16);
1601
1602 case EFI_IFR_NUMERIC_SIZE_4:
1603 return (UINT16)sizeof (UINT32);
1604
1605 case EFI_IFR_NUMERIC_SIZE_8:
1606 return (UINT16)sizeof (UINT64);
1607
1608 default:
1609 ASSERT (FALSE);
1610 return 0;
1611 }
1612
1613 case EFI_IFR_ORDERED_LIST_OP:
1614 NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Header.Length;
1615 //
1616 // OneOfOption must follow the orderedlist opcode.
1617 //
1618 ASSERT (((EFI_IFR_OP_HEADER *)NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);
1619 switch (((EFI_IFR_ONE_OF_OPTION *)NextOpCodeData)->Type) {
1620 case EFI_IFR_TYPE_NUM_SIZE_8:
1621 return (UINT16)sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
1622
1623 case EFI_IFR_TYPE_NUM_SIZE_16:
1624 return (UINT16)sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
1625
1626 case EFI_IFR_TYPE_NUM_SIZE_32:
1627 return (UINT16)sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
1628
1629 case EFI_IFR_TYPE_NUM_SIZE_64:
1630 return (UINT16)sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
1631
1632 default:
1633 ASSERT (FALSE);
1634 return 0;
1635 }
1636
1637 case EFI_IFR_CHECKBOX_OP:
1638 return (UINT16)sizeof (BOOLEAN);
1639
1640 case EFI_IFR_PASSWORD_OP:
1641 return (UINT16)((UINTN)((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize * sizeof (CHAR16));
1642
1643 case EFI_IFR_STRING_OP:
1644 return (UINT16)((UINTN)((EFI_IFR_STRING *)OpCodeData)->MaxSize * sizeof (CHAR16));
1645
1646 case EFI_IFR_DATE_OP:
1647 return (UINT16)sizeof (EFI_HII_DATE);
1648
1649 case EFI_IFR_TIME_OP:
1650 return (UINT16)sizeof (EFI_HII_TIME);
1651
1652 default:
1653 ASSERT (FALSE);
1654 return 0;
1655 }
1656}
1657
1669EFI_STRING
1670EFIAPI
1672 IN EFI_STRING ConfigString
1673 )
1674{
1675 EFI_STRING String;
1676 BOOLEAN Lower;
1677
1678 ASSERT (ConfigString != NULL);
1679
1680 //
1681 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1682 //
1683 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
1684 if (*String == L'=') {
1685 Lower = TRUE;
1686 } else if (*String == L'&') {
1687 Lower = FALSE;
1688 } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
1689 *String = (CHAR16)(*String - L'A' + L'a');
1690 }
1691 }
1692
1693 return ConfigString;
1694}
1695
1713EFI_STRING
1715 IN UINT8 *OpCodeData,
1716 IN EFI_HANDLE DriverHandle
1717 )
1718{
1719 UINTN NameLength;
1720 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1721 UINTN DevicePathSize;
1722 CHAR16 *String;
1723 CHAR16 *ReturnString;
1724 UINTN Index;
1725 UINT8 *Buffer;
1726 CHAR16 *Name;
1727 CHAR8 *AsciiName;
1728 UINTN NameSize;
1729 EFI_GUID *Guid;
1730 UINTN MaxLen;
1731
1732 ASSERT (OpCodeData != NULL);
1733
1734 switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
1735 case EFI_IFR_VARSTORE_OP:
1736 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *)OpCodeData)->Guid;
1737 AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;
1738 break;
1739
1740 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1741 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid;
1742 AsciiName = NULL;
1743 break;
1744
1745 case EFI_IFR_VARSTORE_EFI_OP:
1746 Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid;
1747 AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;
1748 break;
1749
1750 default:
1751 ASSERT (FALSE);
1752 Guid = NULL;
1753 AsciiName = NULL;
1754 break;
1755 }
1756
1757 if (AsciiName != NULL) {
1758 NameSize = AsciiStrSize (AsciiName);
1759 Name = AllocateZeroPool (NameSize * sizeof (CHAR16));
1760 ASSERT (Name != NULL);
1761 AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);
1762 } else {
1763 Name = NULL;
1764 }
1765
1766 //
1767 // Compute the length of Name in Unicode characters.
1768 // If Name is NULL, then the length is 0.
1769 //
1770 NameLength = 0;
1771 if (Name != NULL) {
1772 NameLength = StrLen (Name);
1773 }
1774
1775 DevicePath = NULL;
1776 DevicePathSize = 0;
1777 //
1778 // Retrieve DevicePath Protocol associated with DriverHandle
1779 //
1780 if (DriverHandle != NULL) {
1781 DevicePath = DevicePathFromHandle (DriverHandle);
1782 if (DevicePath == NULL) {
1783 return NULL;
1784 }
1785
1786 //
1787 // Compute the size of the device path in bytes
1788 //
1789 DevicePathSize = GetDevicePathSize (DevicePath);
1790 }
1791
1792 //
1793 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
1794 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
1795 //
1796 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
1797 String = AllocateZeroPool (MaxLen * sizeof (CHAR16));
1798 if (String == NULL) {
1799 return NULL;
1800 }
1801
1802 //
1803 // Start with L"GUID="
1804 //
1805 StrCpyS (String, MaxLen, L"GUID=");
1806 ReturnString = String;
1807 String += StrLen (String);
1808
1809 if (Guid != NULL) {
1810 //
1811 // Append Guid converted to <HexCh>32
1812 //
1813 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
1815 String,
1816 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
1817 PREFIX_ZERO | RADIX_HEX,
1818 *(Buffer++),
1819 2
1820 );
1821 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
1822 }
1823 }
1824
1825 //
1826 // Append L"&NAME="
1827 //
1828 StrCatS (ReturnString, MaxLen, L"&NAME=");
1829 String += StrLen (String);
1830
1831 if (Name != NULL) {
1832 //
1833 // Append Name converted to <Char>NameLength
1834 //
1835 for ( ; *Name != L'\0'; Name++) {
1837 String,
1838 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
1839 PREFIX_ZERO | RADIX_HEX,
1840 *Name,
1841 4
1842 );
1843 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
1844 }
1845 }
1846
1847 //
1848 // Append L"&PATH="
1849 //
1850 StrCatS (ReturnString, MaxLen, L"&PATH=");
1851 String += StrLen (String);
1852
1853 //
1854 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1855 //
1856 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
1858 String,
1859 MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
1860 PREFIX_ZERO | RADIX_HEX,
1861 *(Buffer++),
1862 2
1863 );
1864 String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
1865 }
1866
1867 //
1868 // Null terminate the Unicode string
1869 //
1870 *String = L'\0';
1871
1872 //
1873 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1874 //
1875 return InternalLowerConfigString (ReturnString);
1876}
1877
1888EFI_STRING
1890 IN CHAR16 *Name,
1891 IN UINT16 Offset,
1892 IN UINT16 Width
1893 )
1894{
1895 CHAR16 *StringPtr;
1896 UINTN Length;
1897
1898 if (Name != NULL) {
1899 //
1900 // Add <BlockName> length for each Name
1901 //
1902 // <BlockName> ::= Name + \0
1903 // StrLen(Name) | 1
1904 //
1905 Length = StrLen (Name) + 1;
1906 } else {
1907 //
1908 // Add <BlockName> length for each Offset/Width pair
1909 //
1910 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
1911 // | 7 | 4 | 7 | 4 | 1
1912 //
1913 Length = (7 + 4 + 7 + 4 + 1);
1914 }
1915
1916 //
1917 // Allocate buffer for the entire <ConfigRequest>
1918 //
1919 StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));
1920 ASSERT (StringPtr != NULL);
1921
1922 if (Name != NULL) {
1923 //
1924 // Append Name\0
1925 //
1927 StringPtr,
1928 (StrLen (Name) + 1) * sizeof (CHAR16),
1929 L"%s",
1930 Name
1931 );
1932 } else {
1933 //
1934 // Append OFFSET=XXXX&WIDTH=YYYY\0
1935 //
1937 StringPtr,
1938 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
1939 L"OFFSET=%04X&WIDTH=%04X",
1940 Offset,
1941 Width
1942 );
1943 }
1944
1945 return StringPtr;
1946}
1947
1957CHAR16 *
1959 IN HII_DATABASE_RECORD *DatabaseRecord,
1960 IN EFI_STRING_ID NameId
1961 )
1962{
1963 CHAR16 *Name;
1964 CHAR8 *PlatformLanguage;
1965 CHAR8 *SupportedLanguages;
1966 CHAR8 *BestLanguage;
1967 UINTN StringSize;
1968 CHAR16 TempString;
1969 EFI_STATUS Status;
1970
1971 Name = NULL;
1972 BestLanguage = NULL;
1973 PlatformLanguage = NULL;
1974 SupportedLanguages = NULL;
1975
1976 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
1977 SupportedLanguages = GetSupportedLanguages (DatabaseRecord->Handle);
1978
1979 //
1980 // Get the best matching language from SupportedLanguages
1981 //
1982 BestLanguage = GetBestLanguage (
1983 SupportedLanguages,
1984 FALSE, // RFC 4646 mode
1985 PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority
1986 SupportedLanguages, // Lowest priority
1987 NULL
1988 );
1989 if (BestLanguage == NULL) {
1990 BestLanguage = AllocateCopyPool (sizeof ("en-US"), "en-US");
1991 ASSERT (BestLanguage != NULL);
1992 }
1993
1994 StringSize = 0;
1995 Status = mPrivate.HiiString.GetString (
1996 &mPrivate.HiiString,
1997 BestLanguage,
1998 DatabaseRecord->Handle,
1999 NameId,
2000 &TempString,
2001 &StringSize,
2002 NULL
2003 );
2004 if (Status != EFI_BUFFER_TOO_SMALL) {
2005 goto Done;
2006 }
2007
2008 Name = AllocateZeroPool (StringSize);
2009 if (Name == NULL) {
2010 goto Done;
2011 }
2012
2013 Status = mPrivate.HiiString.GetString (
2014 &mPrivate.HiiString,
2015 BestLanguage,
2016 DatabaseRecord->Handle,
2017 NameId,
2018 Name,
2019 &StringSize,
2020 NULL
2021 );
2022
2023 if (EFI_ERROR (Status)) {
2024 FreePool (Name);
2025 Name = NULL;
2026 goto Done;
2027 }
2028
2029Done:
2030 if (SupportedLanguages != NULL) {
2031 FreePool (SupportedLanguages);
2032 }
2033
2034 if (BestLanguage != NULL) {
2035 FreePool (BestLanguage);
2036 }
2037
2038 if (PlatformLanguage != NULL) {
2039 FreePool (PlatformLanguage);
2040 }
2041
2042 return Name;
2043}
2044
2062 IN HII_DATABASE_RECORD *DatabaseRecord,
2063 IN EFI_STRING_ID KeywordStrId,
2064 OUT UINT8 **OpCodeData,
2065 OUT EFI_STRING *ConfigRequest
2066 )
2067{
2068 LIST_ENTRY *Link;
2069 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
2070 HII_IFR_PACKAGE_INSTANCE *FormPackage;
2072 UINT8 *Storage;
2073 UINT8 *OpCode;
2074 CHAR16 *Name;
2075 UINT16 Offset;
2076 UINT16 Width;
2077 CHAR16 *ConfigHdr;
2078 CHAR16 *RequestElement;
2079 UINTN MaxLen;
2080 CHAR16 *StringPtr;
2081
2082 ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);
2083
2084 OpCode = NULL;
2085 Name = NULL;
2086 Width = 0;
2087 Offset = 0;
2088
2089 PackageListNode = DatabaseRecord->PackageList;
2090
2091 //
2092 // Search the languages in the specified packagelist.
2093 //
2094 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
2095 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
2096
2097 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
2098 if (OpCode != NULL) {
2099 *OpCodeData = OpCode;
2100 Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
2101 //
2102 // Header->VarStoreId == 0 means no storage for this question.
2103 //
2104 if (Header->VarStoreId == 0) {
2105 continue;
2106 }
2107
2108 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
2109 ASSERT (Storage != NULL);
2110
2111 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
2112 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
2113 } else {
2114 Offset = Header->VarStoreInfo.VarOffset;
2115 Width = GetWidth (OpCode);
2116 }
2117
2118 RequestElement = ConstructRequestElement (Name, Offset, Width);
2119 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
2120 ASSERT (ConfigHdr != NULL);
2121
2122 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;
2123 *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
2124 if (*ConfigRequest == NULL) {
2125 FreePool (ConfigHdr);
2126 FreePool (RequestElement);
2127 return EFI_OUT_OF_RESOURCES;
2128 }
2129
2130 StringPtr = *ConfigRequest;
2131
2132 StrCpyS (StringPtr, MaxLen, ConfigHdr);
2133
2134 StrCatS (StringPtr, MaxLen, L"&");
2135
2136 StrCatS (StringPtr, MaxLen, RequestElement);
2137
2138 FreePool (ConfigHdr);
2139 FreePool (RequestElement);
2140
2141 return EFI_SUCCESS;
2142 }
2143 }
2144
2145 return EFI_NOT_FOUND;
2146}
2147
2167 IN HII_DATABASE_RECORD *DatabaseRecord,
2168 IN EFI_STRING_ID KeywordStrId,
2169 IN EFI_STRING ValueElement,
2170 OUT UINT8 **OpCodeData,
2171 OUT EFI_STRING *ConfigResp
2172 )
2173{
2174 LIST_ENTRY *Link;
2175 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
2176 HII_IFR_PACKAGE_INSTANCE *FormPackage;
2178 UINT8 *Storage;
2179 UINT8 *OpCode;
2180 CHAR16 *Name;
2181 UINT16 Offset;
2182 UINT16 Width;
2183 CHAR16 *ConfigHdr;
2184 CHAR16 *RequestElement;
2185 UINTN MaxLen;
2186 CHAR16 *StringPtr;
2187
2188 ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));
2189
2190 OpCode = NULL;
2191 Name = NULL;
2192 Width = 0;
2193 Offset = 0;
2194
2195 PackageListNode = DatabaseRecord->PackageList;
2196
2197 //
2198 // Search the languages in the specified packagelist.
2199 //
2200 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
2201 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
2202
2203 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
2204 if (OpCode != NULL) {
2205 *OpCodeData = OpCode;
2206 Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
2207 //
2208 // Header->VarStoreId == 0 means no storage for this question.
2209 //
2210 ASSERT (Header->VarStoreId != 0);
2211 DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
2212
2213 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
2214 ASSERT (Storage != NULL);
2215
2216 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
2217 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
2218 } else {
2219 Offset = Header->VarStoreInfo.VarOffset;
2220 Width = GetWidth (OpCode);
2221 }
2222
2223 RequestElement = ConstructRequestElement (Name, Offset, Width);
2224
2225 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
2226 ASSERT (ConfigHdr != NULL);
2227
2228 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + StrLen (L"VALUE=") + StrLen (ValueElement) + 1;
2229 *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));
2230 if (*ConfigResp == NULL) {
2231 FreePool (ConfigHdr);
2232 FreePool (RequestElement);
2233 return EFI_OUT_OF_RESOURCES;
2234 }
2235
2236 StringPtr = *ConfigResp;
2237
2238 StrCpyS (StringPtr, MaxLen, ConfigHdr);
2239
2240 StrCatS (StringPtr, MaxLen, L"&");
2241
2242 StrCatS (StringPtr, MaxLen, RequestElement);
2243
2244 StrCatS (StringPtr, MaxLen, L"&");
2245
2246 StrCatS (StringPtr, MaxLen, L"VALUE=");
2247
2248 StrCatS (StringPtr, MaxLen, ValueElement);
2249
2250 FreePool (ConfigHdr);
2251 FreePool (RequestElement);
2252
2253 return EFI_SUCCESS;
2254 }
2255 }
2256
2257 return EFI_NOT_FOUND;
2258}
2259
2275 IN CHAR16 *ConfigRequest,
2276 OUT CHAR16 **ValueElement
2277 )
2278{
2279 EFI_STATUS Status;
2280 EFI_STRING Result;
2281 EFI_STRING Progress;
2282 CHAR16 *StringPtr;
2283 CHAR16 *StringEnd;
2284
2285 ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));
2286
2287 Status = mPrivate.ConfigRouting.ExtractConfig (
2288 &mPrivate.ConfigRouting,
2289 (EFI_STRING)ConfigRequest,
2290 &Progress,
2291 &Result
2292 );
2293 if (EFI_ERROR (Status)) {
2294 return Status;
2295 }
2296
2297 //
2298 // Find Value Section and return it.
2299 //
2300 StringPtr = StrStr (Result, L"&VALUE=");
2301 ASSERT (StringPtr != NULL);
2302 StringEnd = StrStr (StringPtr + 1, L"&");
2303 if (StringEnd != NULL) {
2304 *StringEnd = L'\0';
2305 }
2306
2307 *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);
2308 if (*ValueElement == NULL) {
2309 return EFI_OUT_OF_RESOURCES;
2310 }
2311
2312 if (StringEnd != NULL) {
2313 *StringEnd = L'&';
2314 }
2315
2316 FreePool (Result);
2317
2318 return EFI_SUCCESS;
2319}
2320
2340 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,
2341 IN CHAR8 **NameSpace,
2342 IN CHAR16 *KeywordData,
2343 OUT UINT32 *ProgressErr,
2344 OUT EFI_STRING_ID *KeywordStringId,
2345 OUT HII_DATABASE_RECORD **DataBaseRecord
2346 )
2347{
2348 HII_DATABASE_RECORD *Record;
2349 LIST_ENTRY *Link;
2350 BOOLEAN FindNameSpace;
2351 EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;
2352 UINT8 *DevicePathPkg;
2353 UINTN DevicePathSize;
2354
2355 ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));
2356
2357 FindNameSpace = FALSE;
2358
2359 if (*DevicePath != NULL) {
2360 //
2361 // Get DataBaseRecord from device path protocol.
2362 //
2363 Record = GetRecordFromDevicePath (*DevicePath);
2364 if (Record == NULL) {
2365 //
2366 // Can't find the DatabaseRecord base on the input device path info.
2367 // NEED TO CONFIRM the return ProgressErr.
2368 //
2369 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2370 return EFI_INVALID_PARAMETER;
2371 }
2372
2373 //
2374 // Get string id from the record.
2375 //
2376 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
2377 switch (*ProgressErr) {
2378 case KEYWORD_HANDLER_NO_ERROR:
2379 *DataBaseRecord = Record;
2380 return EFI_SUCCESS;
2381
2382 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:
2383 return EFI_INVALID_PARAMETER;
2384
2385 default:
2386 ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);
2387 return EFI_NOT_FOUND;
2388 }
2389 } else {
2390 //
2391 // Find driver which matches the routing data.
2392 //
2393 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
2394 Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2395
2396 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
2397 if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {
2398 *DataBaseRecord = Record;
2399
2400 if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {
2401 DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));
2402 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);
2403 *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);
2404 if (*DevicePath == NULL) {
2405 return EFI_OUT_OF_RESOURCES;
2406 }
2407 } else {
2408 //
2409 // Need to verify this ASSERT.
2410 //
2411 ASSERT (FALSE);
2412 }
2413
2414 return EFI_SUCCESS;
2415 } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {
2416 return EFI_OUT_OF_RESOURCES;
2417 } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {
2418 FindNameSpace = TRUE;
2419 }
2420 }
2421
2422 //
2423 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
2424 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
2425 //
2426 if (FindNameSpace) {
2427 return EFI_NOT_FOUND;
2428 } else {
2429 return EFI_INVALID_PARAMETER;
2430 }
2431 }
2432}
2433
2452 IN CHAR8 *NameSpace,
2453 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2454 IN EFI_STRING KeywordData,
2455 IN EFI_STRING ValueStr,
2456 IN BOOLEAN ReadOnly,
2457 OUT EFI_STRING *KeywordResp
2458 )
2459{
2460 UINTN RespStrLen;
2461 CHAR16 *RespStr;
2462 CHAR16 *PathHdr;
2463 CHAR16 *UnicodeNameSpace;
2464 UINTN NameSpaceLength;
2465
2466 ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));
2467
2468 //
2469 // 1. Calculate the string length.
2470 //
2471 //
2472 // 1.1 NameSpaceId size.
2473 // 'NAMESPACE='<String>
2474 //
2475 NameSpaceLength = AsciiStrLen (NameSpace);
2476 RespStrLen = 10 + NameSpaceLength;
2477 UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));
2478 if (UnicodeNameSpace == NULL) {
2479 return EFI_OUT_OF_RESOURCES;
2480 }
2481
2482 AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);
2483
2484 //
2485 // 1.2 PathHdr size.
2486 // PATH=<UEFI binary Device Path represented as hex number>'&'
2487 // Attention: The output include the '&' at the end.
2488 //
2490 L"&PATH=",
2492 (VOID *)DevicePath,
2493 1,
2494 &PathHdr
2495 );
2496 RespStrLen += StrLen (PathHdr);
2497
2498 //
2499 // 1.3 Keyword section.
2500 // 'KEYWORD='<String>[':'<DecCh>(1/4)]
2501 //
2502 RespStrLen += 8 + StrLen (KeywordData);
2503
2504 //
2505 // 1.4 Value section.
2506 // ValueStr = '&VALUE='<Number>
2507 //
2508 RespStrLen += StrLen (ValueStr);
2509
2510 //
2511 // 1.5 ReadOnly Section.
2512 // '&READONLY'
2513 //
2514 if (ReadOnly) {
2515 RespStrLen += 9;
2516 }
2517
2518 //
2519 // 2. Allocate the buffer and create the KeywordResp string include '\0'.
2520 //
2521 RespStrLen += 1;
2522 *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));
2523 if (*KeywordResp == NULL) {
2524 if (UnicodeNameSpace != NULL) {
2525 FreePool (UnicodeNameSpace);
2526 }
2527
2528 return EFI_OUT_OF_RESOURCES;
2529 }
2530
2531 RespStr = *KeywordResp;
2532
2533 //
2534 // 2.1 Copy NameSpaceId section.
2535 //
2536 StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");
2537
2538 StrCatS (RespStr, RespStrLen, UnicodeNameSpace);
2539
2540 //
2541 // 2.2 Copy PathHdr section.
2542 //
2543 StrCatS (RespStr, RespStrLen, PathHdr);
2544
2545 //
2546 // 2.3 Copy Keyword section.
2547 //
2548 StrCatS (RespStr, RespStrLen, L"KEYWORD=");
2549
2550 StrCatS (RespStr, RespStrLen, KeywordData);
2551
2552 //
2553 // 2.4 Copy the Value section.
2554 //
2555 StrCatS (RespStr, RespStrLen, ValueStr);
2556
2557 //
2558 // 2.5 Copy ReadOnly section if exist.
2559 //
2560 if (ReadOnly) {
2561 StrCatS (RespStr, RespStrLen, L"&READONLY");
2562 }
2563
2564 if (UnicodeNameSpace != NULL) {
2565 FreePool (UnicodeNameSpace);
2566 }
2567
2568 if (PathHdr != NULL) {
2569 FreePool (PathHdr);
2570 }
2571
2572 return EFI_SUCCESS;
2573}
2574
2589 IN OUT EFI_STRING *MultiKeywordResp,
2590 IN EFI_STRING *KeywordResp
2591 )
2592{
2593 UINTN MultiKeywordRespLen;
2594 EFI_STRING StringPtr;
2595
2596 if (*MultiKeywordResp == NULL) {
2597 *MultiKeywordResp = *KeywordResp;
2598 *KeywordResp = NULL;
2599 return EFI_SUCCESS;
2600 }
2601
2602 MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);
2603
2604 StringPtr = ReallocatePool (
2605 StrSize (*MultiKeywordResp),
2606 MultiKeywordRespLen,
2607 *MultiKeywordResp
2608 );
2609 if (StringPtr == NULL) {
2610 return EFI_OUT_OF_RESOURCES;
2611 }
2612
2613 *MultiKeywordResp = StringPtr;
2614
2615 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");
2616
2617 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);
2618
2619 return EFI_SUCCESS;
2620}
2621
2640 IN CHAR8 *NameSpace,
2641 OUT EFI_STRING *MultiResp,
2642 OUT UINT32 *ProgressErr
2643 )
2644{
2645 LIST_ENTRY *Link;
2646 LIST_ENTRY *StringLink;
2647 UINT8 *DevicePathPkg;
2648 UINT8 *DevicePath;
2649 HII_DATABASE_RECORD *DataBaseRecord;
2650 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
2651 HII_STRING_PACKAGE_INSTANCE *StringPackage;
2652 CHAR8 *LocalNameSpace;
2653 EFI_STRING_ID NextStringId;
2654 EFI_STATUS Status;
2655 UINT8 *OpCode;
2656 CHAR16 *ConfigRequest;
2657 CHAR16 *ValueElement;
2658 CHAR16 *KeywordResp;
2659 CHAR16 *MultiKeywordResp;
2660 CHAR16 *KeywordData;
2661 BOOLEAN ReadOnly;
2662 BOOLEAN FindKeywordPackages;
2663
2664 DataBaseRecord = NULL;
2665 Status = EFI_SUCCESS;
2666 MultiKeywordResp = NULL;
2667 DevicePath = NULL;
2668 LocalNameSpace = NULL;
2669 ConfigRequest = NULL;
2670 ValueElement = NULL;
2671 KeywordResp = NULL;
2672 FindKeywordPackages = FALSE;
2673
2674 if (NameSpace == NULL) {
2675 NameSpace = UEFI_CONFIG_LANG;
2676 }
2677
2678 //
2679 // Find driver which matches the routing data.
2680 //
2681 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
2682 DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2683 if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {
2684 DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2685 }
2686
2687 PackageListNode = DataBaseRecord->PackageList;
2688
2689 for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {
2690 StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
2691
2692 //
2693 // Check whether has keyword string package.
2694 //
2695 if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {
2696 FindKeywordPackages = TRUE;
2697 //
2698 // Keep the NameSpace string.
2699 //
2700 LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
2701 if (LocalNameSpace == NULL) {
2702 return EFI_OUT_OF_RESOURCES;
2703 }
2704
2705 //
2706 // 1 means just begin the enumerate the valid string ids.
2707 // StringId == 1 is always used to save the language for this string package.
2708 // Any valid string start from 2. so here initial it to 1.
2709 //
2710 NextStringId = 1;
2711
2712 //
2713 // Enumerate all valid stringid in the package.
2714 //
2715 while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {
2716 //
2717 // 3.3 Construct the ConfigRequest string.
2718 //
2719 Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);
2720 if (EFI_ERROR (Status)) {
2721 //
2722 // If can't generate ConfigRequest for this question, skip it and start the next.
2723 //
2724 goto Error;
2725 }
2726
2727 //
2728 // 3.4 Extract Value for the input keyword.
2729 //
2730 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
2731 if (EFI_ERROR (Status)) {
2732 if (Status != EFI_OUT_OF_RESOURCES) {
2733 //
2734 // If can't generate ConfigRequest for this question, skip it and start the next.
2735 //
2736 goto Error;
2737 }
2738
2739 //
2740 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2741 //
2742 goto Done;
2743 }
2744
2745 //
2746 // Extract readonly flag from opcode.
2747 //
2748 ReadOnly = ExtractReadOnlyFromOpCode (OpCode);
2749
2750 //
2751 // 5. Generate KeywordResp string.
2752 //
2753 ASSERT (DevicePath != NULL);
2754 Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
2755 if (Status != EFI_SUCCESS) {
2756 //
2757 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2758 //
2759 goto Done;
2760 }
2761
2762 //
2763 // 6. Merge to the MultiKeywordResp string.
2764 //
2765 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
2766 if (EFI_ERROR (Status)) {
2767 goto Done;
2768 }
2769
2770Error:
2771 //
2772 // Clean the temp buffer to later use again.
2773 //
2774 if (ConfigRequest != NULL) {
2775 FreePool (ConfigRequest);
2776 ConfigRequest = NULL;
2777 }
2778
2779 if (ValueElement != NULL) {
2780 FreePool (ValueElement);
2781 ValueElement = NULL;
2782 }
2783
2784 if (KeywordResp != NULL) {
2785 FreePool (KeywordResp);
2786 KeywordResp = NULL;
2787 }
2788 }
2789
2790 if (LocalNameSpace != NULL) {
2791 FreePool (LocalNameSpace);
2792 LocalNameSpace = NULL;
2793 }
2794 }
2795 }
2796 }
2797
2798 //
2799 // return the already get MultiKeywordString even error occurred.
2800 //
2801 if (MultiKeywordResp == NULL) {
2802 Status = EFI_NOT_FOUND;
2803 if (!FindKeywordPackages) {
2804 *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
2805 } else {
2806 *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
2807 }
2808 } else {
2809 Status = EFI_SUCCESS;
2810 }
2811
2812 *MultiResp = MultiKeywordResp;
2813
2814Done:
2815 if (LocalNameSpace != NULL) {
2816 FreePool (LocalNameSpace);
2817 }
2818
2819 if (ConfigRequest != NULL) {
2820 FreePool (ConfigRequest);
2821 }
2822
2823 if (ValueElement != NULL) {
2824 FreePool (ValueElement);
2825 }
2826
2827 return Status;
2828}
2829
2890EFIAPI
2893 IN CONST EFI_STRING KeywordString,
2894 OUT EFI_STRING *Progress,
2895 OUT UINT32 *ProgressErr
2896 )
2897{
2898 CHAR8 *NameSpace;
2899 EFI_STATUS Status;
2900 CHAR16 *StringPtr;
2901 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2902 CHAR16 *NextStringPtr;
2903 CHAR16 *KeywordData;
2904 EFI_STRING_ID KeywordStringId;
2905 UINT32 RetVal;
2906 HII_DATABASE_RECORD *DataBaseRecord;
2907 UINT8 *OpCode;
2908 CHAR16 *ConfigResp;
2909 CHAR16 *MultiConfigResp;
2910 CHAR16 *ValueElement;
2911 BOOLEAN ReadOnly;
2912 EFI_STRING InternalProgress;
2913 CHAR16 *TempString;
2914 CHAR16 *KeywordStartPos;
2915
2916 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {
2917 return EFI_INVALID_PARAMETER;
2918 }
2919
2920 *Progress = KeywordString;
2921 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
2922 Status = EFI_SUCCESS;
2923 MultiConfigResp = NULL;
2924 NameSpace = NULL;
2925 DevicePath = NULL;
2926 KeywordData = NULL;
2927 ValueElement = NULL;
2928 ConfigResp = NULL;
2929 KeywordStartPos = NULL;
2930 KeywordStringId = 0;
2931
2932 //
2933 // Use temp string to avoid changing input string buffer.
2934 //
2935 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
2936 ASSERT (TempString != NULL);
2937 StringPtr = TempString;
2938
2939 while ((StringPtr != NULL) && (*StringPtr != L'\0')) {
2940 //
2941 // 1. Get NameSpace from NameSpaceId keyword.
2942 //
2943 Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);
2944 if (EFI_ERROR (Status)) {
2945 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2946 goto Done;
2947 }
2948
2949 ASSERT (NameSpace != NULL);
2950 //
2951 // 1.1 Check whether the input namespace is valid.
2952 //
2953 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
2954 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2955 Status = EFI_INVALID_PARAMETER;
2956 goto Done;
2957 }
2958
2959 StringPtr = NextStringPtr;
2960
2961 //
2962 // 2. Get possible Device Path info from KeywordString.
2963 //
2964 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
2965 if (EFI_ERROR (Status)) {
2966 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2967 goto Done;
2968 }
2969
2970 StringPtr = NextStringPtr;
2971
2972 //
2973 // 3. Extract keyword from the KeywordRequest string.
2974 //
2975 KeywordStartPos = StringPtr;
2976 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
2977 if (EFI_ERROR (Status)) {
2978 //
2979 // Can't find Keyword base on the input device path info.
2980 //
2981 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2982 Status = EFI_INVALID_PARAMETER;
2983 goto Done;
2984 }
2985
2986 StringPtr = NextStringPtr;
2987
2988 //
2989 // 4. Extract Value from the KeywordRequest string.
2990 //
2991 Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);
2992 if (EFI_ERROR (Status)) {
2993 //
2994 // Can't find Value base on the input device path info.
2995 //
2996 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2997 Status = EFI_INVALID_PARAMETER;
2998 goto Done;
2999 }
3000
3001 StringPtr = NextStringPtr;
3002
3003 //
3004 // 5. Find READONLY tag.
3005 //
3006 if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0)) {
3007 ReadOnly = TRUE;
3008 StringPtr += StrLen (L"&READONLY");
3009 } else {
3010 ReadOnly = FALSE;
3011 }
3012
3013 //
3014 // 6. Get EFI_STRING_ID for the input keyword.
3015 //
3016 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
3017 if (EFI_ERROR (Status)) {
3018 *ProgressErr = RetVal;
3019 goto Done;
3020 }
3021
3022 //
3023 // 7. Construct the ConfigRequest string.
3024 //
3025 Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);
3026 if (EFI_ERROR (Status)) {
3027 goto Done;
3028 }
3029
3030 //
3031 // 8. Check the readonly flag.
3032 //
3033 if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {
3034 //
3035 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
3036 // If not, the input KeywordString must be incorrect, return the error status to caller.
3037 //
3038 *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
3039 Status = EFI_INVALID_PARAMETER;
3040 goto Done;
3041 }
3042
3043 if (ReadOnly) {
3044 *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;
3045 Status = EFI_ACCESS_DENIED;
3046 goto Done;
3047 }
3048
3049 //
3050 // 9. Merge to the MultiKeywordResp string.
3051 //
3052 Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);
3053 if (EFI_ERROR (Status)) {
3054 goto Done;
3055 }
3056
3057 //
3058 // 10. Clean the temp buffer point.
3059 //
3060 FreePool (NameSpace);
3061 FreePool (DevicePath);
3062 FreePool (KeywordData);
3063 FreePool (ValueElement);
3064 NameSpace = NULL;
3065 DevicePath = NULL;
3066 KeywordData = NULL;
3067 ValueElement = NULL;
3068 if (ConfigResp != NULL) {
3069 FreePool (ConfigResp);
3070 ConfigResp = NULL;
3071 }
3072
3073 KeywordStartPos = NULL;
3074 }
3075
3076 //
3077 // 11. Set value to driver.
3078 //
3079 Status = mPrivate.ConfigRouting.RouteConfig (
3080 &mPrivate.ConfigRouting,
3081 (EFI_STRING)MultiConfigResp,
3082 &InternalProgress
3083 );
3084 if (EFI_ERROR (Status)) {
3085 Status = EFI_DEVICE_ERROR;
3086 goto Done;
3087 }
3088
3089 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
3090
3091Done:
3092 if (KeywordStartPos != NULL) {
3093 *Progress = KeywordString + (KeywordStartPos - TempString);
3094 } else {
3095 *Progress = KeywordString + (StringPtr - TempString);
3096 }
3097
3098 ASSERT (TempString != NULL);
3099 FreePool (TempString);
3100 if (NameSpace != NULL) {
3101 FreePool (NameSpace);
3102 }
3103
3104 if (DevicePath != NULL) {
3105 FreePool (DevicePath);
3106 }
3107
3108 if (KeywordData != NULL) {
3109 FreePool (KeywordData);
3110 }
3111
3112 if (ValueElement != NULL) {
3113 FreePool (ValueElement);
3114 }
3115
3116 if (ConfigResp != NULL) {
3117 FreePool (ConfigResp);
3118 }
3119
3120 if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {
3121 FreePool (MultiConfigResp);
3122 }
3123
3124 return Status;
3125}
3126
3197EFIAPI
3200 IN CONST EFI_STRING NameSpaceId OPTIONAL,
3201 IN CONST EFI_STRING KeywordString OPTIONAL,
3202 OUT EFI_STRING *Progress,
3203 OUT UINT32 *ProgressErr,
3204 OUT EFI_STRING *Results
3205 )
3206{
3207 CHAR8 *NameSpace;
3208 EFI_STATUS Status;
3209 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3210 HII_DATABASE_RECORD *DataBaseRecord;
3211 CHAR16 *StringPtr;
3212 CHAR16 *NextStringPtr;
3213 CHAR16 *KeywordData;
3214 EFI_STRING_ID KeywordStringId;
3215 UINT8 *OpCode;
3216 CHAR16 *ConfigRequest;
3217 CHAR16 *ValueElement;
3218 UINT32 RetVal;
3219 BOOLEAN ReadOnly;
3220 CHAR16 *KeywordResp;
3221 CHAR16 *MultiKeywordResp;
3222 CHAR16 *TempString;
3223
3224 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {
3225 return EFI_INVALID_PARAMETER;
3226 }
3227
3228 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
3229 Status = EFI_SUCCESS;
3230 DevicePath = NULL;
3231 NameSpace = NULL;
3232 KeywordData = NULL;
3233 ConfigRequest = NULL;
3234 StringPtr = KeywordString;
3235 ReadOnly = FALSE;
3236 MultiKeywordResp = NULL;
3237 KeywordStringId = 0;
3238 TempString = NULL;
3239
3240 //
3241 // Use temp string to avoid changing input string buffer.
3242 //
3243 if (NameSpaceId != NULL) {
3244 TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);
3245 ASSERT (TempString != NULL);
3246 }
3247
3248 //
3249 // 1. Get NameSpace from NameSpaceId keyword.
3250 //
3251 Status = ExtractNameSpace (TempString, &NameSpace, NULL);
3252 if (TempString != NULL) {
3253 FreePool (TempString);
3254 TempString = NULL;
3255 }
3256
3257 if (EFI_ERROR (Status)) {
3258 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3259 return Status;
3260 }
3261
3262 //
3263 // 1.1 Check whether the input namespace is valid.
3264 //
3265 if (NameSpace != NULL) {
3266 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
3267 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3268 return EFI_INVALID_PARAMETER;
3269 }
3270 }
3271
3272 if (KeywordString != NULL) {
3273 //
3274 // Use temp string to avoid changing input string buffer.
3275 //
3276 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
3277 ASSERT (TempString != NULL);
3278 StringPtr = TempString;
3279
3280 while (*StringPtr != L'\0') {
3281 //
3282 // 2. Get possible Device Path info from KeywordString.
3283 //
3284 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
3285 if (EFI_ERROR (Status)) {
3286 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3287 goto Done;
3288 }
3289
3290 StringPtr = NextStringPtr;
3291
3292 //
3293 // 3. Process Keyword section from the input keywordRequest string.
3294 //
3295 // 3.1 Extract keyword from the KeywordRequest string.
3296 //
3297 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
3298 if (EFI_ERROR (Status)) {
3299 //
3300 // Can't find Keyword base on the input device path info.
3301 //
3302 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3303 Status = EFI_INVALID_PARAMETER;
3304 goto Done;
3305 }
3306
3307 //
3308 // 3.2 Get EFI_STRING_ID for the input keyword.
3309 //
3310 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
3311 if (EFI_ERROR (Status)) {
3312 *ProgressErr = RetVal;
3313 goto Done;
3314 }
3315
3316 //
3317 // 3.3 Construct the ConfigRequest string.
3318 //
3319 Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);
3320 if (EFI_ERROR (Status)) {
3321 goto Done;
3322 }
3323
3324 //
3325 // 3.4 Extract Value for the input keyword.
3326 //
3327 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
3328 if (EFI_ERROR (Status)) {
3329 if (Status != EFI_OUT_OF_RESOURCES) {
3330 Status = EFI_DEVICE_ERROR;
3331 }
3332
3333 goto Done;
3334 }
3335
3336 StringPtr = NextStringPtr;
3337
3338 //
3339 // 4. Process the possible filter section.
3340 //
3341 RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);
3342 if (RetVal != KEYWORD_HANDLER_NO_ERROR) {
3343 *ProgressErr = RetVal;
3344 Status = EFI_INVALID_PARAMETER;
3345 goto Done;
3346 }
3347
3348 StringPtr = NextStringPtr;
3349
3350 //
3351 // 5. Generate KeywordResp string.
3352 //
3353 Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
3354 if (Status != EFI_SUCCESS) {
3355 goto Done;
3356 }
3357
3358 //
3359 // 6. Merge to the MultiKeywordResp string.
3360 //
3361 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
3362 if (EFI_ERROR (Status)) {
3363 goto Done;
3364 }
3365
3366 //
3367 // 7. Update return value.
3368 //
3369 *Results = MultiKeywordResp;
3370
3371 //
3372 // 8. Clean the temp buffer.
3373 //
3374 FreePool (DevicePath);
3375 FreePool (KeywordData);
3376 FreePool (ValueElement);
3377 FreePool (ConfigRequest);
3378 DevicePath = NULL;
3379 KeywordData = NULL;
3380 ValueElement = NULL;
3381 ConfigRequest = NULL;
3382 if (KeywordResp != NULL) {
3383 FreePool (KeywordResp);
3384 KeywordResp = NULL;
3385 }
3386 }
3387 } else {
3388 //
3389 // Enumerate all keyword in the system.
3390 //
3391 Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);
3392 if (EFI_ERROR (Status)) {
3393 goto Done;
3394 }
3395
3396 *Results = MultiKeywordResp;
3397 }
3398
3399 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
3400
3401Done:
3402 *Progress = KeywordString + (StringPtr - TempString);
3403
3404 if (TempString != NULL) {
3405 FreePool (TempString);
3406 }
3407
3408 if (NameSpace != NULL) {
3409 FreePool (NameSpace);
3410 }
3411
3412 if (DevicePath != NULL) {
3413 FreePool (DevicePath);
3414 }
3415
3416 if (KeywordData != NULL) {
3417 FreePool (KeywordData);
3418 }
3419
3420 return Status;
3421}
UINT64 UINTN
UINT64 EFIAPI StrHexToUint64(IN CONST CHAR16 *String)
Definition: String.c:560
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
Definition: Unaligned.c:29
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition: String.c:872
RETURN_STATUS EFIAPI UnicodeStrToAsciiStrS(IN CONST CHAR16 *Source, OUT CHAR8 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2650
RETURN_STATUS EFIAPI StrCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:405
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
Definition: SafeString.c:119
INTN EFIAPI StrnCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
Definition: String.c:162
RETURN_STATUS EFIAPI AsciiStrToUnicodeStrS(IN CONST CHAR8 *Source, OUT CHAR16 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2873
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
HII_DATABASE_RECORD * GetRecordFromDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_STATUS GetStringIdFromDatabase(IN EFI_DEVICE_PATH_PROTOCOL **DevicePath, IN CHAR8 **NameSpace, IN CHAR16 *KeywordData, OUT UINT32 *ProgressErr, OUT EFI_STRING_ID *KeywordStringId, OUT HII_DATABASE_RECORD **DataBaseRecord)
BOOLEAN IsStatementOpCode(IN UINT8 Operand)
EFI_STATUS ExtractValue(IN EFI_STRING String, OUT EFI_STRING *Value, OUT EFI_STRING *NextString)
EFI_STATUS EnumerateAllKeywords(IN CHAR8 *NameSpace, OUT EFI_STRING *MultiResp, OUT UINT32 *ProgressErr)
EFI_STATUS ExtractValueFromDriver(IN CHAR16 *ConfigRequest, OUT CHAR16 **ValueElement)
BOOLEAN IsStorageOpCode(IN UINT8 Operand)
BOOLEAN ExtractFilter(IN EFI_STRING String, OUT UINT8 *FilterFlags, OUT EFI_STRING *NextString)
EFI_STATUS ExtractKeyword(IN EFI_STRING String, OUT EFI_STRING *Keyword, OUT EFI_STRING *NextString)
UINT32 ValidateFilter(IN UINT8 *OpCodeData, IN CHAR16 *KeywordRequest, OUT CHAR16 **NextString, OUT BOOLEAN *ReadOnly)
EFI_STATUS ExtractConfigResp(IN HII_DATABASE_RECORD *DatabaseRecord, IN EFI_STRING_ID KeywordStrId, IN EFI_STRING ValueElement, OUT UINT8 **OpCodeData, OUT EFI_STRING *ConfigResp)
EFI_STATUS EFIAPI EfiConfigKeywordHandlerGetData(IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This, IN CONST EFI_STRING NameSpaceId OPTIONAL, IN CONST EFI_STRING KeywordString OPTIONAL, OUT EFI_STRING *Progress, OUT UINT32 *ProgressErr, OUT EFI_STRING *Results)
EFI_STATUS GenerateKeywordResp(IN CHAR8 *NameSpace, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN EFI_STRING KeywordData, IN EFI_STRING ValueStr, IN BOOLEAN ReadOnly, OUT EFI_STRING *KeywordResp)
EFI_STATUS GetUnicodeStringTextAndSize(IN UINT8 *StringSrc, OUT UINTN *BufferSize, OUT EFI_STRING *StringDest)
EFI_STATUS MergeToMultiKeywordResp(IN OUT EFI_STRING *MultiKeywordResp, IN EFI_STRING *KeywordResp)
EFI_STRING EFIAPI InternalLowerConfigString(IN EFI_STRING ConfigString)
UINT8 * FindQuestionFromStringId(IN HII_IFR_PACKAGE_INSTANCE *FormPackage, IN EFI_STRING_ID KeywordStrId)
EFI_STATUS ExtractNameSpace(IN EFI_STRING String, OUT CHAR8 **NameSpace, OUT EFI_STRING *NextString)
UINT8 * FindStorageFromVarId(IN HII_IFR_PACKAGE_INSTANCE *FormPackage, IN EFI_VARSTORE_ID VarStoreId)
EFI_STATUS ExtractConfigRequest(IN HII_DATABASE_RECORD *DatabaseRecord, IN EFI_STRING_ID KeywordStrId, OUT UINT8 **OpCodeData, OUT EFI_STRING *ConfigRequest)
BOOLEAN ExtractReadOnlyFromOpCode(IN UINT8 *OpCodeData)
UINT16 GetWidth(IN UINT8 *OpCodeData)
UINT32 GetStringIdFromRecord(IN HII_DATABASE_RECORD *DatabaseRecord, IN CHAR8 **NameSpace, IN CHAR16 *KeywordValue, OUT EFI_STRING_ID *StringId)
EFI_STRING_ID GetNextStringId(IN HII_STRING_PACKAGE_INSTANCE *StringPackage, IN EFI_STRING_ID StringId, OUT EFI_STRING *KeywordValue)
EFI_STATUS EFIAPI EfiConfigKeywordHandlerSetData(IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This, IN CONST EFI_STRING KeywordString, OUT EFI_STRING *Progress, OUT UINT32 *ProgressErr)
EFI_STRING ConstructConfigHdr(IN UINT8 *OpCodeData, IN EFI_HANDLE DriverHandle)
EFI_STATUS GetStringIdFromString(IN HII_STRING_PACKAGE_INSTANCE *StringPackage, IN CHAR16 *KeywordValue, OUT EFI_STRING_ID *StringId)
CHAR16 * GetNameFromId(IN HII_DATABASE_RECORD *DatabaseRecord, IN EFI_STRING_ID NameId)
EFI_STATUS ExtractDevicePath(IN EFI_STRING String, OUT UINT8 **DevicePathData, OUT EFI_STRING *NextString)
EFI_STRING ConstructRequestElement(IN CHAR16 *Name, IN UINT16 Offset, IN UINT16 Width)
CHAR8 * GetSupportedLanguages(IN EFI_HII_HANDLE HiiHandle)
VOID GenerateSubStr(IN CONST EFI_STRING String, IN UINTN BufferLen, IN VOID *Buffer, IN UINT8 Flag, OUT EFI_STRING *SubStr)
UINTN EFIAPI DevicePathNodeLength(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
RETURN_STATUS EFIAPI UnicodeValueToStringS(IN OUT CHAR16 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width)
Definition: PrintLib.c:652
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
GUID EFI_GUID
Definition: UefiBaseType.h:25
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1470
CHAR8 *EFIAPI GetBestLanguage(IN CONST CHAR8 *SupportedLanguages, IN UINTN Iso639Language,...)
Definition: UefiLib.c:1522
Definition: Base.h:213