OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ConfigKeywordHandler.c
Go to the documentation of this file.
1
9#include "HiiDatabase.h"
10
12
29EFI_STATUS
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=", L_STR_LEN (L"PATH=")) != 0) {
66 if (StrnCmp (String, L"KEYWORD=", L_STR_LEN (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 += L_STR_LEN (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
169EFI_STATUS
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=", L_STR_LEN (L"NAMESPACE=")) != 0) {
203 return EFI_INVALID_PARAMETER;
204 }
205
206 String += L_STR_LEN (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
249EFI_STATUS
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=", L_STR_LEN (L"KEYWORD=")) != 0) {
279 return EFI_INVALID_PARAMETER;
280 }
281
282 String += L_STR_LEN (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
316EFI_STATUS
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=", L_STR_LEN (L"VALUE=")) != 0) {
335 return EFI_INVALID_PARAMETER;
336 }
337
338 String += L_STR_LEN (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", L_STR_LEN (L"ReadOnly")) == 0) {
404 //
405 // Find ReadOnly filter.
406 //
407 *FilterFlags |= EFI_KEYWORD_FILTER_READONY;
408 String += L_STR_LEN (L"ReadOnly");
409 } else if (StrnCmp (String, L"ReadWrite", L_STR_LEN (L"ReadWrite")) == 0) {
410 //
411 // Find ReadWrite filter.
412 //
413 *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;
414 String += L_STR_LEN (L"ReadWrite");
415 } else if (StrnCmp (String, L"Buffer", L_STR_LEN (L"Buffer")) == 0) {
416 //
417 // Find Buffer Filter.
418 //
419 *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;
420 String += L_STR_LEN (L"Buffer");
421 } else if (StrnCmp (String, L"Numeric", L_STR_LEN (L"Numeric")) == 0) {
422 //
423 // Find Numeric Filter
424 //
425 String += L_STR_LEN (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", L_STR_LEN (L"&PATH")) == 0) ||
455 (StrnCmp (String, L"&KEYWORD", L_STR_LEN (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) {
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
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
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
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
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
732EFI_STATUS
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
777EFI_STATUS
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;
793 EFI_HII_SIBT_EXT2_BLOCK Ext2;
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;
1079 EFI_HII_SIBT_EXT2_BLOCK Ext2;
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++) {
1814 UnicodeValueToStringS (
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++) {
1836 UnicodeValueToStringS (
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++) {
1857 UnicodeValueToStringS (
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 //
1926 UnicodeSPrint (
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 //
1936 UnicodeSPrint (
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 (L_STR_SIZE ("en-US"), "en-US");
1991 ASSERT (BestLanguage != NULL);
1992 }
1993
1994 StringSize = 0;
1995 Status = mPrivate.HiiString.GetString (
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 (
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
2060EFI_STATUS
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;
2071 EFI_IFR_QUESTION_HEADER *Header;
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 ASSERT (Header->VarStoreId != 0);
2105 DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
2106
2107 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
2108 ASSERT (Storage != NULL);
2109
2110 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
2111 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
2112 } else {
2113 Offset = Header->VarStoreInfo.VarOffset;
2114 Width = GetWidth (OpCode);
2115 }
2116
2117 RequestElement = ConstructRequestElement (Name, Offset, Width);
2118 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
2119 ASSERT (ConfigHdr != NULL);
2120
2121 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;
2122 *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
2123 if (*ConfigRequest == NULL) {
2124 FreePool (ConfigHdr);
2125 FreePool (RequestElement);
2126 return EFI_OUT_OF_RESOURCES;
2127 }
2128
2129 StringPtr = *ConfigRequest;
2130
2131 StrCpyS (StringPtr, MaxLen, ConfigHdr);
2132
2133 StrCatS (StringPtr, MaxLen, L"&");
2134
2135 StrCatS (StringPtr, MaxLen, RequestElement);
2136
2137 FreePool (ConfigHdr);
2138 FreePool (RequestElement);
2139
2140 return EFI_SUCCESS;
2141 }
2142 }
2143
2144 return EFI_NOT_FOUND;
2145}
2146
2164EFI_STATUS
2166 IN HII_DATABASE_RECORD *DatabaseRecord,
2167 IN EFI_STRING_ID KeywordStrId,
2168 IN EFI_STRING ValueElement,
2169 OUT UINT8 **OpCodeData,
2170 OUT EFI_STRING *ConfigResp
2171 )
2172{
2173 LIST_ENTRY *Link;
2174 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
2175 HII_IFR_PACKAGE_INSTANCE *FormPackage;
2176 EFI_IFR_QUESTION_HEADER *Header;
2177 UINT8 *Storage;
2178 UINT8 *OpCode;
2179 CHAR16 *Name;
2180 UINT16 Offset;
2181 UINT16 Width;
2182 CHAR16 *ConfigHdr;
2183 CHAR16 *RequestElement;
2184 UINTN MaxLen;
2185 CHAR16 *StringPtr;
2186
2187 ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));
2188
2189 OpCode = NULL;
2190 Name = NULL;
2191 Width = 0;
2192 Offset = 0;
2193
2194 PackageListNode = DatabaseRecord->PackageList;
2195
2196 //
2197 // Search the languages in the specified packagelist.
2198 //
2199 for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
2200 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
2201
2202 OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
2203 if (OpCode != NULL) {
2204 *OpCodeData = OpCode;
2205 Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
2206 //
2207 // Header->VarStoreId == 0 means no storage for this question.
2208 //
2209 ASSERT (Header->VarStoreId != 0);
2210 DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
2211
2212 Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
2213 ASSERT (Storage != NULL);
2214
2215 if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
2216 Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
2217 } else {
2218 Offset = Header->VarStoreInfo.VarOffset;
2219 Width = GetWidth (OpCode);
2220 }
2221
2222 RequestElement = ConstructRequestElement (Name, Offset, Width);
2223
2224 ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
2225 ASSERT (ConfigHdr != NULL);
2226
2227 MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + L_STR_LEN (L"VALUE=") + StrLen (ValueElement) + 1;
2228 *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));
2229 if (*ConfigResp == NULL) {
2230 FreePool (ConfigHdr);
2231 FreePool (RequestElement);
2232 return EFI_OUT_OF_RESOURCES;
2233 }
2234
2235 StringPtr = *ConfigResp;
2236
2237 StrCpyS (StringPtr, MaxLen, ConfigHdr);
2238
2239 StrCatS (StringPtr, MaxLen, L"&");
2240
2241 StrCatS (StringPtr, MaxLen, RequestElement);
2242
2243 StrCatS (StringPtr, MaxLen, L"&");
2244
2245 StrCatS (StringPtr, MaxLen, L"VALUE=");
2246
2247 StrCatS (StringPtr, MaxLen, ValueElement);
2248
2249 FreePool (ConfigHdr);
2250 FreePool (RequestElement);
2251
2252 return EFI_SUCCESS;
2253 }
2254 }
2255
2256 return EFI_NOT_FOUND;
2257}
2258
2272EFI_STATUS
2274 IN CHAR16 *ConfigRequest,
2275 OUT CHAR16 **ValueElement
2276 )
2277{
2278 EFI_STATUS Status;
2279 EFI_STRING Result;
2280 EFI_STRING Progress;
2281 CHAR16 *StringPtr;
2282 CHAR16 *StringEnd;
2283
2284 ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));
2285
2286 Status = mPrivate.ConfigRouting.ExtractConfig (
2288 (EFI_STRING)ConfigRequest,
2289 &Progress,
2290 &Result
2291 );
2292 if (EFI_ERROR (Status)) {
2293 return Status;
2294 }
2295
2296 //
2297 // Find Value Section and return it.
2298 //
2299 StringPtr = StrStr (Result, L"&VALUE=");
2300 ASSERT (StringPtr != NULL);
2301 StringEnd = StrStr (StringPtr + 1, L"&");
2302 if (StringEnd != NULL) {
2303 *StringEnd = L'\0';
2304 }
2305
2306 *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);
2307 if (*ValueElement == NULL) {
2308 return EFI_OUT_OF_RESOURCES;
2309 }
2310
2311 if (StringEnd != NULL) {
2312 *StringEnd = L'&';
2313 }
2314
2315 FreePool (Result);
2316
2317 return EFI_SUCCESS;
2318}
2319
2337EFI_STATUS
2339 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,
2340 IN CHAR8 **NameSpace,
2341 IN CHAR16 *KeywordData,
2342 OUT UINT32 *ProgressErr,
2343 OUT EFI_STRING_ID *KeywordStringId,
2344 OUT HII_DATABASE_RECORD **DataBaseRecord
2345 )
2346{
2347 HII_DATABASE_RECORD *Record;
2348 LIST_ENTRY *Link;
2349 BOOLEAN FindNameSpace;
2350 EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;
2351 UINT8 *DevicePathPkg;
2352 UINTN DevicePathSize;
2353
2354 ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));
2355
2356 FindNameSpace = FALSE;
2357
2358 if (*DevicePath != NULL) {
2359 //
2360 // Get DataBaseRecord from device path protocol.
2361 //
2362 Record = GetRecordFromDevicePath (*DevicePath);
2363 if (Record == NULL) {
2364 //
2365 // Can't find the DatabaseRecord base on the input device path info.
2366 // NEED TO CONFIRM the return ProgressErr.
2367 //
2368 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2369 return EFI_INVALID_PARAMETER;
2370 }
2371
2372 //
2373 // Get string id from the record.
2374 //
2375 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
2376 switch (*ProgressErr) {
2377 case KEYWORD_HANDLER_NO_ERROR:
2378 *DataBaseRecord = Record;
2379 return EFI_SUCCESS;
2380
2381 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:
2382 return EFI_INVALID_PARAMETER;
2383
2384 default:
2385 ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);
2386 return EFI_NOT_FOUND;
2387 }
2388 } else {
2389 //
2390 // Find driver which matches the routing data.
2391 //
2392 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
2393 Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2394
2395 *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
2396 if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {
2397 *DataBaseRecord = Record;
2398
2399 if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {
2400 DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));
2401 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);
2402 *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);
2403 if (*DevicePath == NULL) {
2404 return EFI_OUT_OF_RESOURCES;
2405 }
2406 } else {
2407 //
2408 // Need to verify this ASSERT.
2409 //
2410 ASSERT (FALSE);
2411 }
2412
2413 return EFI_SUCCESS;
2414 } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {
2415 return EFI_OUT_OF_RESOURCES;
2416 } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {
2417 FindNameSpace = TRUE;
2418 }
2419 }
2420
2421 //
2422 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
2423 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
2424 //
2425 if (FindNameSpace) {
2426 return EFI_NOT_FOUND;
2427 } else {
2428 return EFI_INVALID_PARAMETER;
2429 }
2430 }
2431}
2432
2449EFI_STATUS
2451 IN CHAR8 *NameSpace,
2452 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2453 IN EFI_STRING KeywordData,
2454 IN EFI_STRING ValueStr,
2455 IN BOOLEAN ReadOnly,
2456 OUT EFI_STRING *KeywordResp
2457 )
2458{
2459 UINTN RespStrLen;
2460 CHAR16 *RespStr;
2461 CHAR16 *PathHdr;
2462 CHAR16 *UnicodeNameSpace;
2463 UINTN NameSpaceLength;
2464
2465 ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));
2466
2467 //
2468 // 1. Calculate the string length.
2469 //
2470 //
2471 // 1.1 NameSpaceId size.
2472 // 'NAMESPACE='<String>
2473 //
2474 NameSpaceLength = AsciiStrLen (NameSpace);
2475 RespStrLen = 10 + NameSpaceLength;
2476 UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));
2477 if (UnicodeNameSpace == NULL) {
2478 return EFI_OUT_OF_RESOURCES;
2479 }
2480
2481 AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);
2482
2483 //
2484 // 1.2 PathHdr size.
2485 // PATH=<UEFI binary Device Path represented as hex number>'&'
2486 // Attention: The output include the '&' at the end.
2487 //
2489 L"&PATH=",
2490 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
2491 (VOID *)DevicePath,
2492 1,
2493 &PathHdr
2494 );
2495 RespStrLen += StrLen (PathHdr);
2496
2497 //
2498 // 1.3 Keyword section.
2499 // 'KEYWORD='<String>[':'<DecCh>(1/4)]
2500 //
2501 RespStrLen += 8 + StrLen (KeywordData);
2502
2503 //
2504 // 1.4 Value section.
2505 // ValueStr = '&VALUE='<Number>
2506 //
2507 RespStrLen += StrLen (ValueStr);
2508
2509 //
2510 // 1.5 ReadOnly Section.
2511 // '&READONLY'
2512 //
2513 if (ReadOnly) {
2514 RespStrLen += 9;
2515 }
2516
2517 //
2518 // 2. Allocate the buffer and create the KeywordResp string include '\0'.
2519 //
2520 RespStrLen += 1;
2521 *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));
2522 if (*KeywordResp == NULL) {
2523 if (UnicodeNameSpace != NULL) {
2524 FreePool (UnicodeNameSpace);
2525 }
2526
2527 return EFI_OUT_OF_RESOURCES;
2528 }
2529
2530 RespStr = *KeywordResp;
2531
2532 //
2533 // 2.1 Copy NameSpaceId section.
2534 //
2535 StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");
2536
2537 StrCatS (RespStr, RespStrLen, UnicodeNameSpace);
2538
2539 //
2540 // 2.2 Copy PathHdr section.
2541 //
2542 StrCatS (RespStr, RespStrLen, PathHdr);
2543
2544 //
2545 // 2.3 Copy Keyword section.
2546 //
2547 StrCatS (RespStr, RespStrLen, L"KEYWORD=");
2548
2549 StrCatS (RespStr, RespStrLen, KeywordData);
2550
2551 //
2552 // 2.4 Copy the Value section.
2553 //
2554 StrCatS (RespStr, RespStrLen, ValueStr);
2555
2556 //
2557 // 2.5 Copy ReadOnly section if exist.
2558 //
2559 if (ReadOnly) {
2560 StrCatS (RespStr, RespStrLen, L"&READONLY");
2561 }
2562
2563 if (UnicodeNameSpace != NULL) {
2564 FreePool (UnicodeNameSpace);
2565 }
2566
2567 if (PathHdr != NULL) {
2568 FreePool (PathHdr);
2569 }
2570
2571 return EFI_SUCCESS;
2572}
2573
2586EFI_STATUS
2588 IN OUT EFI_STRING *MultiKeywordResp,
2589 IN EFI_STRING *KeywordResp
2590 )
2591{
2592 UINTN MultiKeywordRespLen;
2593 EFI_STRING StringPtr;
2594
2595 if (*MultiKeywordResp == NULL) {
2596 *MultiKeywordResp = *KeywordResp;
2597 *KeywordResp = NULL;
2598 return EFI_SUCCESS;
2599 }
2600
2601 MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);
2602
2603 StringPtr = ReallocatePool (
2604 StrSize (*MultiKeywordResp),
2605 MultiKeywordRespLen,
2606 *MultiKeywordResp
2607 );
2608 if (StringPtr == NULL) {
2609 return EFI_OUT_OF_RESOURCES;
2610 }
2611
2612 *MultiKeywordResp = StringPtr;
2613
2614 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");
2615
2616 StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);
2617
2618 return EFI_SUCCESS;
2619}
2620
2637EFI_STATUS
2639 IN CHAR8 *NameSpace,
2640 OUT EFI_STRING *MultiResp,
2641 OUT UINT32 *ProgressErr
2642 )
2643{
2644 LIST_ENTRY *Link;
2645 LIST_ENTRY *StringLink;
2646 UINT8 *DevicePathPkg;
2647 UINT8 *DevicePath;
2648 HII_DATABASE_RECORD *DataBaseRecord;
2649 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
2650 HII_STRING_PACKAGE_INSTANCE *StringPackage;
2651 CHAR8 *LocalNameSpace;
2652 EFI_STRING_ID NextStringId;
2653 EFI_STATUS Status;
2654 UINT8 *OpCode;
2655 CHAR16 *ConfigRequest;
2656 CHAR16 *ValueElement;
2657 CHAR16 *KeywordResp;
2658 CHAR16 *MultiKeywordResp;
2659 CHAR16 *KeywordData;
2660 BOOLEAN ReadOnly;
2661 BOOLEAN FindKeywordPackages;
2662
2663 DataBaseRecord = NULL;
2664 Status = EFI_SUCCESS;
2665 MultiKeywordResp = NULL;
2666 DevicePath = NULL;
2667 LocalNameSpace = NULL;
2668 ConfigRequest = NULL;
2669 ValueElement = NULL;
2670 KeywordResp = NULL;
2671 FindKeywordPackages = FALSE;
2672
2673 if (NameSpace == NULL) {
2674 NameSpace = UEFI_CONFIG_LANG;
2675 }
2676
2677 //
2678 // Find driver which matches the routing data.
2679 //
2680 for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
2681 DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2682 if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {
2683 DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2684 }
2685
2686 PackageListNode = DataBaseRecord->PackageList;
2687
2688 for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {
2689 StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
2690
2691 //
2692 // Check whether has keyword string package.
2693 //
2694 if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {
2695 FindKeywordPackages = TRUE;
2696 //
2697 // Keep the NameSpace string.
2698 //
2699 LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
2700 if (LocalNameSpace == NULL) {
2701 return EFI_OUT_OF_RESOURCES;
2702 }
2703
2704 //
2705 // 1 means just begin the enumerate the valid string ids.
2706 // StringId == 1 is always used to save the language for this string package.
2707 // Any valid string start from 2. so here initial it to 1.
2708 //
2709 NextStringId = 1;
2710
2711 //
2712 // Enumerate all valid stringid in the package.
2713 //
2714 while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {
2715 //
2716 // 3.3 Construct the ConfigRequest string.
2717 //
2718 Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);
2719 if (EFI_ERROR (Status)) {
2720 //
2721 // If can't generate ConfigRequest for this question, skip it and start the next.
2722 //
2723 goto Error;
2724 }
2725
2726 //
2727 // 3.4 Extract Value for the input keyword.
2728 //
2729 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
2730 if (EFI_ERROR (Status)) {
2731 if (Status != EFI_OUT_OF_RESOURCES) {
2732 //
2733 // If can't generate ConfigRequest for this question, skip it and start the next.
2734 //
2735 goto Error;
2736 }
2737
2738 //
2739 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2740 //
2741 goto Done;
2742 }
2743
2744 //
2745 // Extract readonly flag from opcode.
2746 //
2747 ReadOnly = ExtractReadOnlyFromOpCode (OpCode);
2748
2749 //
2750 // 5. Generate KeywordResp string.
2751 //
2752 ASSERT (DevicePath != NULL);
2753 Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
2754 if (Status != EFI_SUCCESS) {
2755 //
2756 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2757 //
2758 goto Done;
2759 }
2760
2761 //
2762 // 6. Merge to the MultiKeywordResp string.
2763 //
2764 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
2765 if (EFI_ERROR (Status)) {
2766 goto Done;
2767 }
2768
2769Error:
2770 //
2771 // Clean the temp buffer to later use again.
2772 //
2773 if (ConfigRequest != NULL) {
2774 FreePool (ConfigRequest);
2775 ConfigRequest = NULL;
2776 }
2777
2778 if (ValueElement != NULL) {
2779 FreePool (ValueElement);
2780 ValueElement = NULL;
2781 }
2782
2783 if (KeywordResp != NULL) {
2784 FreePool (KeywordResp);
2785 KeywordResp = NULL;
2786 }
2787 }
2788
2789 if (LocalNameSpace != NULL) {
2790 FreePool (LocalNameSpace);
2791 LocalNameSpace = NULL;
2792 }
2793 }
2794 }
2795 }
2796
2797 //
2798 // return the already get MultiKeywordString even error occurred.
2799 //
2800 if (MultiKeywordResp == NULL) {
2801 Status = EFI_NOT_FOUND;
2802 if (!FindKeywordPackages) {
2803 *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
2804 } else {
2805 *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
2806 }
2807 } else {
2808 Status = EFI_SUCCESS;
2809 }
2810
2811 *MultiResp = MultiKeywordResp;
2812
2813Done:
2814 if (LocalNameSpace != NULL) {
2815 FreePool (LocalNameSpace);
2816 }
2817
2818 if (ConfigRequest != NULL) {
2819 FreePool (ConfigRequest);
2820 }
2821
2822 if (ValueElement != NULL) {
2823 FreePool (ValueElement);
2824 }
2825
2826 return Status;
2827}
2828
2888EFI_STATUS
2889EFIAPI
2891 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
2892 IN CONST EFI_STRING KeywordString,
2893 OUT EFI_STRING *Progress,
2894 OUT UINT32 *ProgressErr
2895 )
2896{
2897 CHAR8 *NameSpace;
2898 EFI_STATUS Status;
2899 CHAR16 *StringPtr;
2900 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2901 CHAR16 *NextStringPtr;
2902 CHAR16 *KeywordData;
2903 EFI_STRING_ID KeywordStringId;
2904 UINT32 RetVal;
2905 HII_DATABASE_RECORD *DataBaseRecord;
2906 UINT8 *OpCode;
2907 CHAR16 *ConfigResp;
2908 CHAR16 *MultiConfigResp;
2909 CHAR16 *ValueElement;
2910 BOOLEAN ReadOnly;
2911 EFI_STRING InternalProgress;
2912 CHAR16 *TempString;
2913 CHAR16 *KeywordStartPos;
2914
2915 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {
2916 return EFI_INVALID_PARAMETER;
2917 }
2918
2919 *Progress = KeywordString;
2920 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
2921 Status = EFI_SUCCESS;
2922 MultiConfigResp = NULL;
2923 NameSpace = NULL;
2924 DevicePath = NULL;
2925 KeywordData = NULL;
2926 ValueElement = NULL;
2927 ConfigResp = NULL;
2928 KeywordStartPos = NULL;
2929 KeywordStringId = 0;
2930
2931 //
2932 // Use temp string to avoid changing input string buffer.
2933 //
2934 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
2935 ASSERT (TempString != NULL);
2936 StringPtr = TempString;
2937
2938 while ((StringPtr != NULL) && (*StringPtr != L'\0')) {
2939 //
2940 // 1. Get NameSpace from NameSpaceId keyword.
2941 //
2942 Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);
2943 if (EFI_ERROR (Status)) {
2944 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2945 goto Done;
2946 }
2947
2948 ASSERT (NameSpace != NULL);
2949 //
2950 // 1.1 Check whether the input namespace is valid.
2951 //
2952 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, L_STR_LEN (UEFI_CONFIG_LANG)) != 0) {
2953 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2954 Status = EFI_INVALID_PARAMETER;
2955 goto Done;
2956 }
2957
2958 StringPtr = NextStringPtr;
2959
2960 //
2961 // 2. Get possible Device Path info from KeywordString.
2962 //
2963 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
2964 if (EFI_ERROR (Status)) {
2965 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2966 goto Done;
2967 }
2968
2969 StringPtr = NextStringPtr;
2970
2971 //
2972 // 3. Extract keyword from the KeywordRequest string.
2973 //
2974 KeywordStartPos = StringPtr;
2975 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
2976 if (EFI_ERROR (Status)) {
2977 //
2978 // Can't find Keyword base on the input device path info.
2979 //
2980 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2981 Status = EFI_INVALID_PARAMETER;
2982 goto Done;
2983 }
2984
2985 StringPtr = NextStringPtr;
2986
2987 //
2988 // 4. Extract Value from the KeywordRequest string.
2989 //
2990 Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);
2991 if (EFI_ERROR (Status)) {
2992 //
2993 // Can't find Value base on the input device path info.
2994 //
2995 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
2996 Status = EFI_INVALID_PARAMETER;
2997 goto Done;
2998 }
2999
3000 StringPtr = NextStringPtr;
3001
3002 //
3003 // 5. Find READONLY tag.
3004 //
3005 if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", L_STR_LEN (L"&READONLY")) == 0)) {
3006 ReadOnly = TRUE;
3007 StringPtr += L_STR_LEN (L"&READONLY");
3008 } else {
3009 ReadOnly = FALSE;
3010 }
3011
3012 //
3013 // 6. Get EFI_STRING_ID for the input keyword.
3014 //
3015 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
3016 if (EFI_ERROR (Status)) {
3017 *ProgressErr = RetVal;
3018 goto Done;
3019 }
3020
3021 //
3022 // 7. Construct the ConfigRequest string.
3023 //
3024 Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);
3025 if (EFI_ERROR (Status)) {
3026 goto Done;
3027 }
3028
3029 //
3030 // 8. Check the readonly flag.
3031 //
3032 if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {
3033 //
3034 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
3035 // If not, the input KeywordString must be incorrect, return the error status to caller.
3036 //
3037 *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
3038 Status = EFI_INVALID_PARAMETER;
3039 goto Done;
3040 }
3041
3042 if (ReadOnly) {
3043 *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;
3044 Status = EFI_ACCESS_DENIED;
3045 goto Done;
3046 }
3047
3048 //
3049 // 9. Merge to the MultiKeywordResp string.
3050 //
3051 Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);
3052 if (EFI_ERROR (Status)) {
3053 goto Done;
3054 }
3055
3056 //
3057 // 10. Clean the temp buffer point.
3058 //
3059 FreePool (NameSpace);
3060 FreePool (DevicePath);
3061 FreePool (KeywordData);
3062 FreePool (ValueElement);
3063 NameSpace = NULL;
3064 DevicePath = NULL;
3065 KeywordData = NULL;
3066 ValueElement = NULL;
3067 if (ConfigResp != NULL) {
3068 FreePool (ConfigResp);
3069 ConfigResp = NULL;
3070 }
3071
3072 KeywordStartPos = NULL;
3073 }
3074
3075 //
3076 // 11. Set value to driver.
3077 //
3078 Status = mPrivate.ConfigRouting.RouteConfig (
3080 (EFI_STRING)MultiConfigResp,
3081 &InternalProgress
3082 );
3083 if (EFI_ERROR (Status)) {
3084 Status = EFI_DEVICE_ERROR;
3085 goto Done;
3086 }
3087
3088 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
3089
3090Done:
3091 if (KeywordStartPos != NULL) {
3092 *Progress = KeywordString + (KeywordStartPos - TempString);
3093 } else {
3094 *Progress = KeywordString + (StringPtr - TempString);
3095 }
3096
3097 ASSERT (TempString != NULL);
3098 FreePool (TempString);
3099 if (NameSpace != NULL) {
3100 FreePool (NameSpace);
3101 }
3102
3103 if (DevicePath != NULL) {
3104 FreePool (DevicePath);
3105 }
3106
3107 if (KeywordData != NULL) {
3108 FreePool (KeywordData);
3109 }
3110
3111 if (ValueElement != NULL) {
3112 FreePool (ValueElement);
3113 }
3114
3115 if (ConfigResp != NULL) {
3116 FreePool (ConfigResp);
3117 }
3118
3119 if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {
3120 FreePool (MultiConfigResp);
3121 }
3122
3123 return Status;
3124}
3125
3195EFI_STATUS
3196EFIAPI
3198 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
3199 IN CONST EFI_STRING NameSpaceId, OPTIONAL
3200 IN CONST EFI_STRING KeywordString, OPTIONAL
3201 OUT EFI_STRING *Progress,
3202 OUT UINT32 *ProgressErr,
3203 OUT EFI_STRING *Results
3204 )
3205{
3206 CHAR8 *NameSpace;
3207 EFI_STATUS Status;
3208 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3209 HII_DATABASE_RECORD *DataBaseRecord;
3210 CHAR16 *StringPtr;
3211 CHAR16 *NextStringPtr;
3212 CHAR16 *KeywordData;
3213 EFI_STRING_ID KeywordStringId;
3214 UINT8 *OpCode;
3215 CHAR16 *ConfigRequest;
3216 CHAR16 *ValueElement;
3217 UINT32 RetVal;
3218 BOOLEAN ReadOnly;
3219 CHAR16 *KeywordResp;
3220 CHAR16 *MultiKeywordResp;
3221 CHAR16 *TempString;
3222
3223 if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {
3224 return EFI_INVALID_PARAMETER;
3225 }
3226
3227 *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
3228 Status = EFI_SUCCESS;
3229 DevicePath = NULL;
3230 NameSpace = NULL;
3231 KeywordData = NULL;
3232 ConfigRequest = NULL;
3233 StringPtr = KeywordString;
3234 ReadOnly = FALSE;
3235 MultiKeywordResp = NULL;
3236 KeywordStringId = 0;
3237 TempString = NULL;
3238
3239 //
3240 // Use temp string to avoid changing input string buffer.
3241 //
3242 if (NameSpaceId != NULL) {
3243 TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);
3244 ASSERT (TempString != NULL);
3245 }
3246
3247 //
3248 // 1. Get NameSpace from NameSpaceId keyword.
3249 //
3250 Status = ExtractNameSpace (TempString, &NameSpace, NULL);
3251 if (TempString != NULL) {
3252 FreePool (TempString);
3253 TempString = NULL;
3254 }
3255
3256 if (EFI_ERROR (Status)) {
3257 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3258 return Status;
3259 }
3260
3261 //
3262 // 1.1 Check whether the input namespace is valid.
3263 //
3264 if (NameSpace != NULL) {
3265 if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, L_STR_LEN (UEFI_CONFIG_LANG)) != 0) {
3266 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3267 return EFI_INVALID_PARAMETER;
3268 }
3269 }
3270
3271 if (KeywordString != NULL) {
3272 //
3273 // Use temp string to avoid changing input string buffer.
3274 //
3275 TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
3276 ASSERT (TempString != NULL);
3277 StringPtr = TempString;
3278
3279 while (*StringPtr != L'\0') {
3280 //
3281 // 2. Get possible Device Path info from KeywordString.
3282 //
3283 Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
3284 if (EFI_ERROR (Status)) {
3285 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3286 goto Done;
3287 }
3288
3289 StringPtr = NextStringPtr;
3290
3291 //
3292 // 3. Process Keyword section from the input keywordRequest string.
3293 //
3294 // 3.1 Extract keyword from the KeywordRequest string.
3295 //
3296 Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
3297 if (EFI_ERROR (Status)) {
3298 //
3299 // Can't find Keyword base on the input device path info.
3300 //
3301 *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
3302 Status = EFI_INVALID_PARAMETER;
3303 goto Done;
3304 }
3305
3306 //
3307 // 3.2 Get EFI_STRING_ID for the input keyword.
3308 //
3309 Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
3310 if (EFI_ERROR (Status)) {
3311 *ProgressErr = RetVal;
3312 goto Done;
3313 }
3314
3315 //
3316 // 3.3 Construct the ConfigRequest string.
3317 //
3318 Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);
3319 if (EFI_ERROR (Status)) {
3320 goto Done;
3321 }
3322
3323 //
3324 // 3.4 Extract Value for the input keyword.
3325 //
3326 Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
3327 if (EFI_ERROR (Status)) {
3328 if (Status != EFI_OUT_OF_RESOURCES) {
3329 Status = EFI_DEVICE_ERROR;
3330 }
3331
3332 goto Done;
3333 }
3334
3335 StringPtr = NextStringPtr;
3336
3337 //
3338 // 4. Process the possible filter section.
3339 //
3340 RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);
3341 if (RetVal != KEYWORD_HANDLER_NO_ERROR) {
3342 *ProgressErr = RetVal;
3343 Status = EFI_INVALID_PARAMETER;
3344 goto Done;
3345 }
3346
3347 StringPtr = NextStringPtr;
3348
3349 //
3350 // 5. Generate KeywordResp string.
3351 //
3352 Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
3353 if (Status != EFI_SUCCESS) {
3354 goto Done;
3355 }
3356
3357 //
3358 // 6. Merge to the MultiKeywordResp string.
3359 //
3360 Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
3361 if (EFI_ERROR (Status)) {
3362 goto Done;
3363 }
3364
3365 //
3366 // 7. Update return value.
3367 //
3368 *Results = MultiKeywordResp;
3369
3370 //
3371 // 8. Clean the temp buffer.
3372 //
3373 FreePool (DevicePath);
3374 FreePool (KeywordData);
3375 FreePool (ValueElement);
3376 FreePool (ConfigRequest);
3377 DevicePath = NULL;
3378 KeywordData = NULL;
3379 ValueElement = NULL;
3380 ConfigRequest = NULL;
3381 if (KeywordResp != NULL) {
3382 FreePool (KeywordResp);
3383 KeywordResp = NULL;
3384 }
3385 }
3386 } else {
3387 //
3388 // Enumerate all keyword in the system.
3389 //
3390 Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);
3391 if (EFI_ERROR (Status)) {
3392 goto Done;
3393 }
3394
3395 *Results = MultiKeywordResp;
3396 }
3397
3398 *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
3399
3400Done:
3401 *Progress = KeywordString + (StringPtr - TempString);
3402
3403 if (TempString != NULL) {
3404 FreePool (TempString);
3405 }
3406
3407 if (NameSpace != NULL) {
3408 FreePool (NameSpace);
3409 }
3410
3411 if (DevicePath != NULL) {
3412 FreePool (DevicePath);
3413 }
3414
3415 if (KeywordData != NULL) {
3416 FreePool (KeywordData);
3417 }
3418
3419 return Status;
3420}
UINT16 BlockSize
Definition Apm.h:32
VENDOR_DEVICE_PATH Header
UINT64 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 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 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 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)
HII_DATABASE_PRIVATE_DATA mPrivate
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)
void Error(char *FileName, uint32_t LineNumber, uint32_t ErrorCode, char *OffendingText, char *MsgFmt,...)
Definition EfiLdrImage.c:57
#define EFI_KEYWORD_FILTER_REAWRITE
#define EFI_KEYWORD_FILTER_NUMERIC_2
#define HII_DATABASE_RECORD_SIGNATURE
#define EFI_KEYWORD_FILTER_NUMERIC_1
#define EFI_KEYWORD_FILTER_NUMERIC_8
#define EFI_KEYWORD_FILTER_BUFFER
#define EFI_KEYWORD_FILTER_READONY
#define HII_IFR_PACKAGE_SIGNATURE
#define HII_STRING_PACKAGE_SIGNATURE
#define EFI_KEYWORD_FILTER_NUMERIC
#define EFI_KEYWORD_FILTER_NUMERIC_4
#define L_STR_LEN(String)
Definition OcStringLib.h:26
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
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)
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
Definition UserMisc.c:680
#define ASSERT(x)
Definition coder.h:55
EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting
EFI_HII_STRING_PROTOCOL HiiString
HII_DATABASE_PACKAGE_LIST_INSTANCE * PackageList
EFI_HII_STRING_PACKAGE_HDR * StringPkgHdr