OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ConfigRouting.c
Go to the documentation of this file.
1
9#include "HiiDatabase.h"
11
24UINTN
26 IN EFI_STRING String
27 )
28{
29 EFI_STRING TmpPtr;
30
31 //
32 // "GUID=" should be the first element of incoming string.
33 //
34 ASSERT (String != NULL);
35 ASSERT (StrnCmp (String, L"GUID=", L_STR_LEN (L"GUID=")) == 0);
36
37 //
38 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
39 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
40 //
41 TmpPtr = StrStr (String, L"&GUID=");
42 if (TmpPtr == NULL) {
43 return StrLen (String);
44 }
45
46 return (TmpPtr - String);
47}
48
65EFI_STATUS
67 IN EFI_STRING String,
68 OUT UINT8 **DevicePathData
69 )
70{
71 UINTN Length;
72 EFI_STRING PathHdr;
73 UINT8 *DevicePathBuffer;
74 CHAR16 TemStr[2];
75 UINTN Index;
76 UINT8 DigitUint8;
77 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
78
79 if ((String == NULL) || (DevicePathData == NULL)) {
80 return EFI_INVALID_PARAMETER;
81 }
82
83 //
84 // Find the 'PATH=' of <PathHdr> and skip it.
85 //
86 for ( ; (*String != 0 && StrnCmp (String, L"PATH=", L_STR_LEN (L"PATH=")) != 0); String++) {
87 }
88
89 if (*String == 0) {
90 return EFI_INVALID_PARAMETER;
91 }
92
93 //
94 // Check whether path data does exist.
95 //
96 String += L_STR_LEN (L"PATH=");
97 if (*String == 0) {
98 return EFI_INVALID_PARAMETER;
99 }
100
101 PathHdr = String;
102
103 //
104 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
105 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
106 // of UEFI device path.
107 //
108 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {
109 }
110
111 //
112 // Check DevicePath Length
113 //
114 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
115 return EFI_NOT_FOUND;
116 }
117
118 //
119 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
120 // as the device path resides in RAM memory.
121 // Translate the data into binary.
122 //
123 DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);
124 if (DevicePathBuffer == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 //
129 // Convert DevicePath
130 //
131 ZeroMem (TemStr, sizeof (TemStr));
132 for (Index = 0; Index < Length; Index++) {
133 TemStr[0] = PathHdr[Index];
134 DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
135 if ((Index & 1) == 0) {
136 DevicePathBuffer[Index/2] = DigitUint8;
137 } else {
138 DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);
139 }
140 }
141
142 //
143 // Validate DevicePath
144 //
145 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;
146 while (!IsDevicePathEnd (DevicePath)) {
147 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
148 //
149 // Invalid device path
150 //
151 FreePool (DevicePathBuffer);
152 return EFI_NOT_FOUND;
153 }
154
155 DevicePath = NextDevicePathNode (DevicePath);
156 }
157
158 //
159 // return the device path
160 //
161 *DevicePathData = DevicePathBuffer;
162 return EFI_SUCCESS;
163}
164
172VOID
173EFIAPI
175 IN EFI_STRING ConfigString
176 )
177{
178 EFI_STRING String;
179 BOOLEAN Lower;
180
181 ASSERT (ConfigString != NULL);
182
183 //
184 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
185 //
186 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
187 if (*String == L'=') {
188 Lower = TRUE;
189 } else if (*String == L'&') {
190 Lower = FALSE;
191 } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
192 *String = (CHAR16)(*String - L'A' + L'a');
193 }
194 }
195
196 return;
197}
198
221VOID
223 IN CONST EFI_STRING String,
224 IN UINTN BufferLen,
225 IN VOID *Buffer,
226 IN UINT8 Flag,
227 OUT EFI_STRING *SubStr
228 )
229{
230 UINTN Length;
231 EFI_STRING Str;
232 EFI_STRING StringHeader;
233 CHAR16 *TemString;
234 CHAR16 *TemName;
235 UINT8 *TemBuffer;
236 UINTN Index;
237
238 ASSERT (String != NULL && SubStr != NULL);
239
240 if (Buffer == NULL) {
241 *SubStr = AllocateCopyPool (StrSize (String), String);
242 ASSERT (*SubStr != NULL);
243 return;
244 }
245
246 //
247 // Header + Data + '&' + '\0'
248 //
249 Length = StrLen (String) + BufferLen * 2 + 1 + 1;
250 Str = AllocateZeroPool (Length * sizeof (CHAR16));
251 ASSERT (Str != NULL);
252
253 StrCpyS (Str, Length, String);
254
255 StringHeader = Str + StrLen (String);
256 TemString = (CHAR16 *)StringHeader;
257
258 switch (Flag) {
259 case 1:
260 //
261 // Convert Buffer to Hex String in reverse order
262 //
263 TemBuffer = ((UINT8 *)Buffer);
264 for (Index = 0; Index < BufferLen; Index++, TemBuffer++) {
265 UnicodeValueToStringS (
266 TemString,
267 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
268 PREFIX_ZERO | RADIX_HEX,
269 *TemBuffer,
270 2
271 );
272 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
273 }
274
275 break;
276 case 2:
277 //
278 // Check buffer is enough
279 //
280 TemName = (CHAR16 *)Buffer;
281 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
282 //
283 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
284 //
285 for ( ; *TemName != L'\0'; TemName++) {
286 UnicodeValueToStringS (
287 TemString,
288 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
289 PREFIX_ZERO | RADIX_HEX,
290 *TemName,
291 4
292 );
293 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
294 }
295
296 break;
297 case 3:
298 //
299 // Convert Buffer to Hex String
300 //
301 TemBuffer = ((UINT8 *)Buffer) + BufferLen - 1;
302 for (Index = 0; Index < BufferLen; Index++, TemBuffer--) {
303 UnicodeValueToStringS (
304 TemString,
305 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
306 PREFIX_ZERO | RADIX_HEX,
307 *TemBuffer,
308 2
309 );
310 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
311 }
312
313 break;
314 default:
315 break;
316 }
317
318 //
319 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
320 //
321 StrCatS (Str, Length, L"&");
322 HiiToLower (Str);
323
324 *SubStr = Str;
325}
326
342EFI_STATUS
344 IN EFI_STRING String,
345 OUT EFI_STRING *ConfigBody
346 )
347{
348 EFI_STRING TmpPtr;
349 EFI_STRING Result;
350 UINTN Length;
351
352 if ((String == NULL) || (ConfigBody == NULL)) {
353 return EFI_INVALID_PARAMETER;
354 }
355
356 //
357 // The setting information should start OFFSET, not ALTCFG.
358 //
359 if (StrnCmp (String, L"&ALTCFG=", L_STR_LEN (L"&ALTCFG=")) == 0) {
360 return EFI_INVALID_PARAMETER;
361 }
362
363 TmpPtr = StrStr (String, L"GUID=");
364 if (TmpPtr == NULL) {
365 //
366 // It is the last <ConfigResp> of the incoming configuration string.
367 //
368 Result = AllocateCopyPool (StrSize (String), String);
369 if (Result == NULL) {
370 return EFI_OUT_OF_RESOURCES;
371 } else {
372 *ConfigBody = Result;
373 return EFI_SUCCESS;
374 }
375 }
376
377 Length = TmpPtr - String;
378 if (Length == 0) {
379 return EFI_NOT_FOUND;
380 }
381
382 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
383 if (Result == NULL) {
384 return EFI_OUT_OF_RESOURCES;
385 }
386
387 *(Result + Length - 1) = 0;
388 *ConfigBody = Result;
389 return EFI_SUCCESS;
390}
391
408EFI_STATUS
410 IN OUT EFI_STRING *MultiString,
411 IN EFI_STRING AppendString
412 )
413{
414 UINTN AppendStringSize;
415 UINTN MultiStringSize;
416 UINTN MaxLen;
417
418 if ((MultiString == NULL) || (*MultiString == NULL) || (AppendString == NULL)) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 AppendStringSize = StrSize (AppendString);
423 MultiStringSize = StrSize (*MultiString);
424 MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
425
426 //
427 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
428 //
429 if ((MultiStringSize + AppendStringSize > MAX_STRING_LENGTH) ||
430 (MultiStringSize > MAX_STRING_LENGTH))
431 {
432 *MultiString = (EFI_STRING)ReallocatePool (
433 MultiStringSize,
434 MultiStringSize + AppendStringSize,
435 (VOID *)(*MultiString)
436 );
437 MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
438 ASSERT (*MultiString != NULL);
439 }
440
441 //
442 // Append the incoming string
443 //
444 StrCatS (*MultiString, MaxLen, AppendString);
445
446 return EFI_SUCCESS;
447}
448
468EFI_STATUS
470 IN EFI_STRING StringPtr,
471 OUT UINT8 **Number,
472 OUT UINTN *Len
473 )
474{
475 EFI_STRING TmpPtr;
476 UINTN Length;
477 EFI_STRING Str;
478 UINT8 *Buf;
479 EFI_STATUS Status;
480 UINT8 DigitUint8;
481 UINTN Index;
482 CHAR16 TemStr[2];
483
484 if ((StringPtr == NULL) || (*StringPtr == L'\0') || (Number == NULL) || (Len == NULL)) {
485 return EFI_INVALID_PARAMETER;
486 }
487
488 Buf = NULL;
489
490 TmpPtr = StringPtr;
491 while (*StringPtr != L'\0' && *StringPtr != L'&') {
492 StringPtr++;
493 }
494
495 *Len = StringPtr - TmpPtr;
496 Length = *Len + 1;
497
498 Str = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
499 if (Str == NULL) {
500 Status = EFI_OUT_OF_RESOURCES;
501 goto Exit;
502 }
503
504 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
505 *(Str + *Len) = L'\0';
506
507 Length = (Length + 1) / 2;
508 Buf = (UINT8 *)AllocateZeroPool (Length);
509 if (Buf == NULL) {
510 Status = EFI_OUT_OF_RESOURCES;
511 goto Exit;
512 }
513
514 Length = *Len;
515 ZeroMem (TemStr, sizeof (TemStr));
516 for (Index = 0; Index < Length; Index++) {
517 TemStr[0] = Str[Length - Index - 1];
518 DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
519 if ((Index & 1) == 0) {
520 Buf[Index/2] = DigitUint8;
521 } else {
522 Buf[Index/2] = (UINT8)((DigitUint8 << 4) + Buf[Index/2]);
523 }
524 }
525
526 *Number = Buf;
527 Status = EFI_SUCCESS;
528
529Exit:
530 if (Str != NULL) {
531 FreePool (Str);
532 }
533
534 return Status;
535}
536
550EFI_STATUS
552 IN EFI_STRING String,
553 IN EFI_STRING BlockName,
554 IN UINT8 *Buffer,
555 OUT BOOLEAN *Found,
556 IN UINTN BufferLen
557 )
558{
559 EFI_STRING BlockPtr;
560 UINTN Length;
561 UINT8 *TempBuffer;
562 EFI_STATUS Status;
563
564 TempBuffer = NULL;
565 *Found = FALSE;
566 BlockPtr = StrStr (String, BlockName);
567
568 while (BlockPtr != NULL) {
569 BlockPtr += StrLen (BlockName);
570 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
571 if (EFI_ERROR (Status)) {
572 return Status;
573 }
574
575 ASSERT (TempBuffer != NULL);
576 if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
577 *Found = TRUE;
578 FreePool (TempBuffer);
579 TempBuffer = NULL;
580 return EFI_SUCCESS;
581 } else {
582 FreePool (TempBuffer);
583 TempBuffer = NULL;
584 BlockPtr = StrStr (BlockPtr + 1, BlockName);
585 }
586 }
587
588 return EFI_SUCCESS;
589}
590
608EFI_STATUS
610 IN EFI_STRING DefaultAltCfgResp,
611 IN OUT EFI_STRING *ConfigAltResp,
612 IN EFI_STRING AltConfigHdr,
613 IN OUT BOOLEAN *ConfigAltRespChanged
614 )
615{
616 EFI_STATUS Status;
617 EFI_STRING BlockPtr;
618 EFI_STRING BlockPtrStart;
619 EFI_STRING StringPtr;
620 EFI_STRING AppendString;
621 EFI_STRING AltConfigHdrPtr;
622 UINT8 *TempBuffer;
623 UINTN OffsetLength;
624 UINTN AppendSize;
625 UINTN TotalSize;
626 BOOLEAN FoundOffset;
627
628 AppendString = NULL;
629 TempBuffer = NULL;
630 //
631 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
632 //
633 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
634 ASSERT (AltConfigHdrPtr != NULL);
635 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
636 //
637 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
638 //
639 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
640 ASSERT (StringPtr != NULL);
641
642 while (BlockPtr != NULL) {
643 //
644 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
645 //
646 BlockPtrStart = BlockPtr;
647 BlockPtr += L_STR_LEN (L"&OFFSET=");
648 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
649 if (EFI_ERROR (Status)) {
650 Status = EFI_OUT_OF_RESOURCES;
651 goto Exit;
652 }
653
654 //
655 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
656 //
657 Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
658 if (TempBuffer != NULL) {
659 FreePool (TempBuffer);
660 TempBuffer = NULL;
661 }
662
663 if (EFI_ERROR (Status)) {
664 Status = EFI_OUT_OF_RESOURCES;
665 goto Exit;
666 }
667
668 if (!FoundOffset) {
669 //
670 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
671 // Calculate the size of <BlockConfig>.
672 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
673 //
674 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
675 if (BlockPtr != NULL) {
676 AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
677 } else {
678 AppendSize = StrSize (BlockPtrStart);
679 }
680
681 //
682 // Copy the <BlockConfig> to AppendString.
683 //
684 if (AppendString == NULL) {
685 AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
686 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
687 } else {
688 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
689 AppendString = (EFI_STRING)ReallocatePool (
690 StrSize (AppendString),
691 TotalSize,
692 AppendString
693 );
694 if (AppendString == NULL) {
695 Status = EFI_OUT_OF_RESOURCES;
696 goto Exit;
697 }
698
699 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
700 }
701 } else {
702 //
703 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
704 //
705 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
706 }
707 }
708
709 if (AppendString != NULL) {
710 //
711 // Reallocate ConfigAltResp to copy the AppendString.
712 //
713 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
714 *ConfigAltResp = (EFI_STRING)ReallocatePool (
715 StrSize (*ConfigAltResp),
716 TotalSize,
717 *ConfigAltResp
718 );
719 if (*ConfigAltResp == NULL) {
720 Status = EFI_OUT_OF_RESOURCES;
721 goto Exit;
722 }
723
724 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
725 *ConfigAltRespChanged = TRUE;
726 }
727
728 Status = EFI_SUCCESS;
729
730Exit:
731 if (AppendString != NULL) {
732 FreePool (AppendString);
733 }
734
735 return Status;
736}
737
755EFI_STATUS
757 IN EFI_STRING DefaultAltCfgResp,
758 IN OUT EFI_STRING *ConfigAltResp,
759 IN EFI_STRING AltConfigHdr,
760 IN OUT BOOLEAN *ConfigAltRespChanged
761 )
762{
763 EFI_STATUS Status;
764 EFI_STRING NvConfigPtr;
765 EFI_STRING NvConfigStart;
766 EFI_STRING NvConfigValuePtr;
767 EFI_STRING StringPtr;
768 EFI_STRING NvConfigExist;
769 EFI_STRING AppendString;
770 CHAR16 TempChar;
771 UINTN AppendSize;
772 UINTN TotalSize;
773
774 AppendString = NULL;
775 NvConfigExist = NULL;
776 //
777 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
778 //
779 NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
780 ASSERT (NvConfigPtr != NULL);
781 NvConfigPtr = StrStr (NvConfigPtr + StrLen (AltConfigHdr), L"&");
782 //
783 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
784 //
785 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
786 ASSERT (StringPtr != NULL);
787 StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
788 ASSERT (StringPtr != NULL);
789
790 while (NvConfigPtr != NULL) {
791 //
792 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
793 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
794 //
795 NvConfigStart = NvConfigPtr;
796 NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
797 ASSERT (NvConfigValuePtr != NULL);
798 TempChar = *NvConfigValuePtr;
799 *NvConfigValuePtr = L'\0';
800 //
801 // Get the <Label> with AltConfigHdr in ConfigAltResp.
802 //
803 NvConfigExist = StrStr (StringPtr, NvConfigPtr);
804 if (NvConfigExist == NULL) {
805 //
806 // Don't find same <Label> in ConfigAltResp.
807 // Calculate the size of <NvConfig>.
808 //
809 *NvConfigValuePtr = TempChar;
810 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
811 if (NvConfigPtr != NULL) {
812 AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
813 } else {
814 AppendSize = StrSize (NvConfigStart);
815 }
816
817 //
818 // Copy the <NvConfig> to AppendString.
819 //
820 if (AppendString == NULL) {
821 AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
822 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
823 } else {
824 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
825 AppendString = (EFI_STRING)ReallocatePool (
826 StrSize (AppendString),
827 TotalSize,
828 AppendString
829 );
830 if (AppendString == NULL) {
831 Status = EFI_OUT_OF_RESOURCES;
832 goto Exit;
833 }
834
835 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
836 }
837 } else {
838 //
839 // To find next <Label> in DefaultAltCfgResp.
840 //
841 *NvConfigValuePtr = TempChar;
842 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
843 }
844 }
845
846 if (AppendString != NULL) {
847 //
848 // Reallocate ConfigAltResp to copy the AppendString.
849 //
850 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
851 *ConfigAltResp = (EFI_STRING)ReallocatePool (
852 StrSize (*ConfigAltResp),
853 StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
854 *ConfigAltResp
855 );
856 if (*ConfigAltResp == NULL) {
857 Status = EFI_OUT_OF_RESOURCES;
858 goto Exit;
859 }
860
861 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
862 *ConfigAltRespChanged = TRUE;
863 }
864
865 Status = EFI_SUCCESS;
866
867Exit:
868 if (AppendString != NULL) {
869 FreePool (AppendString);
870 }
871
872 return Status;
873}
874
892EFI_STATUS
894 IN OUT EFI_STRING *AltCfgResp,
895 IN EFI_STRING DefaultAltCfgResp,
896 IN EFI_STRING AltConfigHdr
897 )
898{
899 EFI_STATUS Status;
900 EFI_STRING AltCfgRespBackup;
901 EFI_STRING AltConfigHdrPtr;
902 EFI_STRING AltConfigHdrPtrNext;
903 EFI_STRING ConfigAltResp;
904 EFI_STRING StringPtr;
905 EFI_STRING StringPtrNext;
906 EFI_STRING BlockPtr;
907 UINTN ReallocateSize;
908 CHAR16 TempChar;
909 CHAR16 TempCharA;
910 BOOLEAN ConfigAltRespChanged;
911
912 Status = EFI_OUT_OF_RESOURCES;
913 BlockPtr = NULL;
914 AltConfigHdrPtrNext = NULL;
915 StringPtrNext = NULL;
916 ConfigAltResp = NULL;
917 AltCfgRespBackup = NULL;
918 TempChar = L'\0';
919 TempCharA = L'\0';
920 ConfigAltRespChanged = FALSE;
921
922 //
923 // To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
924 //
925 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
926 ASSERT (AltConfigHdrPtr != NULL);
927 AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
928 if (AltConfigHdrPtrNext != NULL) {
929 TempChar = *AltConfigHdrPtrNext;
930 *AltConfigHdrPtrNext = L'\0';
931 }
932
933 //
934 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
935 //
936 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
937 ASSERT (StringPtr != NULL);
938 StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
939 if (StringPtrNext != NULL) {
940 TempCharA = *StringPtrNext;
941 *StringPtrNext = L'\0';
942 }
943
944 //
945 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
946 //
947 ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
948 if (ConfigAltResp == NULL) {
949 goto Exit;
950 }
951
952 //
953 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
954 //
955 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
956 if (BlockPtr != NULL) {
957 //
958 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
959 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
960 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
961 //
962 Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
963 if (EFI_ERROR (Status)) {
964 goto Exit;
965 }
966 } else {
967 //
968 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
969 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
970 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
971 //
972 Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
973 if (EFI_ERROR (Status)) {
974 goto Exit;
975 }
976 }
977
978 //
979 // Restore the AltCfgResp.
980 //
981 if (StringPtrNext != NULL) {
982 *StringPtrNext = TempCharA;
983 }
984
985 //
986 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
987 //
988 if (!ConfigAltRespChanged) {
989 Status = EFI_SUCCESS;
990 goto Exit;
991 }
992
993 //
994 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
995 //
996 if (StringPtrNext != NULL) {
997 ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
998 } else {
999 ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
1000 }
1001
1002 AltCfgRespBackup = (EFI_STRING)AllocateZeroPool (ReallocateSize);
1003 if (AltCfgRespBackup == NULL) {
1004 goto Exit;
1005 }
1006
1007 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
1008 if (StringPtrNext != NULL) {
1009 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
1010 }
1011
1012 FreePool (*AltCfgResp);
1013 *AltCfgResp = AltCfgRespBackup;
1014
1015 Status = EFI_SUCCESS;
1016
1017Exit:
1018 if (ConfigAltResp != NULL) {
1019 FreePool (ConfigAltResp);
1020 }
1021
1022 //
1023 // Restore the DefaultAltCfgResp.
1024 //
1025 if ( AltConfigHdrPtrNext != NULL) {
1026 *AltConfigHdrPtrNext = TempChar;
1027 AltConfigHdrPtrNext = NULL;
1028 }
1029
1030 return Status;
1031}
1032
1048EFI_STATUS
1049EFIAPI
1051 IN OUT EFI_STRING *AltCfgResp,
1052 IN EFI_STRING DefaultAltCfgResp
1053 )
1054{
1055 EFI_STRING StringPtrDefault;
1056 EFI_STRING StringPtrEnd;
1057 CHAR16 TempChar;
1058 EFI_STRING StringPtr;
1059 EFI_STRING AltConfigHdr;
1060 UINTN HeaderLength;
1061 UINTN SizeAltCfgResp;
1062 UINTN MaxLen;
1063 UINTN TotalSize;
1064
1065 if (*AltCfgResp == NULL) {
1066 return EFI_INVALID_PARAMETER;
1067 }
1068
1069 //
1070 // Get the request ConfigHdr
1071 //
1072 SizeAltCfgResp = 0;
1073 StringPtr = *AltCfgResp;
1074
1075 //
1076 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1077 //
1078 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
1079 return EFI_INVALID_PARAMETER;
1080 }
1081
1082 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", L_STR_LEN (L"&NAME=")) != 0) {
1083 StringPtr++;
1084 }
1085
1086 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", L_STR_LEN (L"&PATH=")) != 0) {
1087 StringPtr++;
1088 }
1089
1090 if (*StringPtr == L'\0') {
1091 return EFI_INVALID_PARAMETER;
1092 }
1093
1094 StringPtr += L_STR_LEN (L"&PATH=");
1095 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1096 StringPtr++;
1097 }
1098
1099 HeaderLength = StringPtr - *AltCfgResp;
1100
1101 //
1102 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1103 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1104 //
1105 MaxLen = 1 + HeaderLength + 8 + 4 + 1;
1106 AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
1107 if (AltConfigHdr == NULL) {
1108 return EFI_OUT_OF_RESOURCES;
1109 }
1110
1111 StrCpyS (AltConfigHdr, MaxLen, L"&");
1112 StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
1113 StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
1114 HeaderLength = StrLen (AltConfigHdr);
1115
1116 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
1117 while (StringPtrDefault != NULL) {
1118 //
1119 // Get AltCfg Name
1120 //
1121 StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
1122 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
1123
1124 //
1125 // Append the found default value string to the input AltCfgResp
1126 //
1127 if (StringPtr == NULL) {
1128 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
1129 SizeAltCfgResp = StrSize (*AltCfgResp);
1130 if (StringPtrEnd == NULL) {
1131 //
1132 // No more default string is found.
1133 //
1134 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1135 *AltCfgResp = (EFI_STRING)ReallocatePool (
1136 SizeAltCfgResp,
1137 TotalSize,
1138 (VOID *)(*AltCfgResp)
1139 );
1140 if (*AltCfgResp == NULL) {
1141 FreePool (AltConfigHdr);
1142 return EFI_OUT_OF_RESOURCES;
1143 }
1144
1145 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1146 break;
1147 } else {
1148 TempChar = *StringPtrEnd;
1149 *StringPtrEnd = L'\0';
1150 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1151 *AltCfgResp = (EFI_STRING)ReallocatePool (
1152 SizeAltCfgResp,
1153 TotalSize,
1154 (VOID *)(*AltCfgResp)
1155 );
1156 if (*AltCfgResp == NULL) {
1157 *StringPtrEnd = TempChar;
1158 FreePool (AltConfigHdr);
1159 return EFI_OUT_OF_RESOURCES;
1160 }
1161
1162 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1163 *StringPtrEnd = TempChar;
1164 }
1165 } else {
1166 //
1167 // The AltCfgResp contains <AltCfgResp>.
1168 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1169 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1170 //
1171 CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
1172 }
1173
1174 //
1175 // Find next AltCfg String
1176 //
1177 *(AltConfigHdr + HeaderLength) = L'\0';
1178 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
1179 }
1180
1181 FreePool (AltConfigHdr);
1182 return EFI_SUCCESS;
1183}
1184
1192VOID
1194 IN IFR_BLOCK_DATA *BlockData,
1195 IN IFR_DEFAULT_DATA *DefaultValueData
1196 )
1197{
1198 LIST_ENTRY *Link;
1199 IFR_DEFAULT_DATA *DefaultValueArray;
1200 LIST_ENTRY *DefaultLink;
1201
1202 DefaultLink = &BlockData->DefaultValueEntry;
1203
1204 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
1205 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
1206 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
1207 //
1208 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1209 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1210 //
1211 if ((DefaultValueData->Type > DefaultValueArray->Type) || ((DefaultValueData->Type == DefaultValueArray->Type) && (DefaultValueData->Type == DefaultValueFromOtherDefault))) {
1212 //
1213 // Update the default value array in BlockData.
1214 //
1215 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
1216 DefaultValueArray->Type = DefaultValueData->Type;
1217 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
1218 }
1219
1220 return;
1221 }
1222 }
1223
1224 //
1225 // Insert new default value data in tail.
1226 //
1227 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1228 ASSERT (DefaultValueArray != NULL);
1229 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
1230 InsertTailList (Link, &DefaultValueArray->Entry);
1231}
1232
1240VOID
1242 IN LIST_ENTRY *BlockLink,
1243 IN IFR_BLOCK_DATA **BlockData
1244 )
1245{
1246 LIST_ENTRY *Link;
1247 IFR_BLOCK_DATA *BlockArray;
1248 IFR_BLOCK_DATA *BlockSingleData;
1249
1250 BlockSingleData = *BlockData;
1251
1252 if (BlockSingleData->Name != NULL) {
1253 InsertTailList (BlockLink, &BlockSingleData->Entry);
1254 return;
1255 }
1256
1257 //
1258 // Insert block data in its Offset and Width order.
1259 //
1260 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
1261 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1262 if (BlockArray->Offset == BlockSingleData->Offset) {
1263 if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && (BlockArray->Width == BlockSingleData->Width))) {
1264 //
1265 // Insert this block data in the front of block array
1266 //
1267 InsertTailList (Link, &BlockSingleData->Entry);
1268 return;
1269 }
1270
1271 if ((!BlockSingleData->IsBitVar) && (BlockArray->Width == BlockSingleData->Width)) {
1272 //
1273 // The same block array has been added.
1274 //
1275 if (BlockSingleData != BlockArray) {
1276 FreePool (BlockSingleData);
1277 *BlockData = BlockArray;
1278 }
1279
1280 return;
1281 }
1282 } else if (BlockArray->Offset > BlockSingleData->Offset) {
1283 //
1284 // Insert new block data in the front of block array
1285 //
1286 InsertTailList (Link, &BlockSingleData->Entry);
1287 return;
1288 }
1289 }
1290
1291 //
1292 // Add new block data into the tail.
1293 //
1294 InsertTailList (Link, &BlockSingleData->Entry);
1295}
1296
1315CHAR8 *
1317 IN EFI_HII_HANDLE HiiHandle
1318 )
1319{
1320 EFI_STATUS Status;
1321 UINTN LanguageSize;
1322 CHAR8 TempSupportedLanguages;
1323 CHAR8 *SupportedLanguages;
1324
1325 ASSERT (HiiHandle != NULL);
1326
1327 //
1328 // Retrieve the size required for the supported languages buffer.
1329 //
1330 LanguageSize = 0;
1331 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
1332
1333 //
1334 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1335 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1336 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1337 // in the HII Database
1338 //
1339 if (Status != EFI_BUFFER_TOO_SMALL) {
1340 //
1341 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1342 //
1343 return NULL;
1344 }
1345
1346 //
1347 // Allocate the supported languages buffer.
1348 //
1349 SupportedLanguages = AllocateZeroPool (LanguageSize);
1350 if (SupportedLanguages == NULL) {
1351 //
1352 // Return NULL if allocation fails.
1353 //
1354 return NULL;
1355 }
1356
1357 //
1358 // Retrieve the supported languages string
1359 //
1360 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
1361 if (EFI_ERROR (Status)) {
1362 //
1363 // Free the buffer and return NULL if the supported languages can not be retrieved.
1364 //
1365 FreePool (SupportedLanguages);
1366 return NULL;
1367 }
1368
1369 //
1370 // Return the Null-terminated ASCII string of supported languages
1371 //
1372 return SupportedLanguages;
1373}
1374
1389EFI_STRING
1391 IN EFI_HII_HANDLE HiiHandle,
1392 IN EFI_STRING_ID StringId
1393 )
1394{
1395 EFI_STATUS Status;
1396 UINTN StringSize;
1397 CHAR16 TempString;
1398 EFI_STRING String;
1399 CHAR8 *SupportedLanguages;
1400 CHAR8 *PlatformLanguage;
1401 CHAR8 *BestLanguage;
1402 CHAR8 *Language;
1403
1404 ASSERT (HiiHandle != NULL);
1405 ASSERT (StringId != 0);
1406
1407 //
1408 // Initialize all allocated buffers to NULL
1409 //
1410 SupportedLanguages = NULL;
1411 PlatformLanguage = NULL;
1412 BestLanguage = NULL;
1413 String = NULL;
1414 Language = "";
1415
1416 //
1417 // Get the languages that the package specified by HiiHandle supports
1418 //
1419 SupportedLanguages = GetSupportedLanguages (HiiHandle);
1420 if (SupportedLanguages == NULL) {
1421 goto Error;
1422 }
1423
1424 //
1425 // Get the current platform language setting
1426 //
1427 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
1428
1429 //
1430 // Get the best matching language from SupportedLanguages
1431 //
1432 BestLanguage = GetBestLanguage (
1433 SupportedLanguages,
1434 FALSE, // RFC 4646 mode
1435 Language, // Highest priority
1436 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
1437 SupportedLanguages, // Lowest priority
1438 NULL
1439 );
1440 if (BestLanguage == NULL) {
1441 goto Error;
1442 }
1443
1444 //
1445 // Retrieve the size of the string in the string package for the BestLanguage
1446 //
1447 StringSize = 0;
1448 Status = mPrivate.HiiString.GetString (
1450 BestLanguage,
1451 HiiHandle,
1452 StringId,
1453 &TempString,
1454 &StringSize,
1455 NULL
1456 );
1457 //
1458 // If GetString() returns EFI_SUCCESS for a zero size,
1459 // then there are no supported languages registered for HiiHandle. If GetString()
1460 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1461 // in the HII Database
1462 //
1463 if (Status != EFI_BUFFER_TOO_SMALL) {
1464 goto Error;
1465 }
1466
1467 //
1468 // Allocate a buffer for the return string
1469 //
1470 String = AllocateZeroPool (StringSize);
1471 if (String == NULL) {
1472 goto Error;
1473 }
1474
1475 //
1476 // Retrieve the string from the string package
1477 //
1478 Status = mPrivate.HiiString.GetString (
1480 BestLanguage,
1481 HiiHandle,
1482 StringId,
1483 String,
1484 &StringSize,
1485 NULL
1486 );
1487 if (EFI_ERROR (Status)) {
1488 //
1489 // Free the buffer and return NULL if the supported languages can not be retrieved.
1490 //
1491 FreePool (String);
1492 String = NULL;
1493 }
1494
1495Error:
1496 //
1497 // Free allocated buffers
1498 //
1499 if (SupportedLanguages != NULL) {
1500 FreePool (SupportedLanguages);
1501 }
1502
1503 if (PlatformLanguage != NULL) {
1504 FreePool (PlatformLanguage);
1505 }
1506
1507 if (BestLanguage != NULL) {
1508 FreePool (BestLanguage);
1509 }
1510
1511 //
1512 // Return the Null-terminated Unicode string
1513 //
1514 return String;
1515}
1516
1529BOOLEAN
1531 IN IFR_BLOCK_DATA *RequestBlockArray,
1532 IN UINT16 VarOffset,
1533 IN UINT16 VarWidth,
1534 IN BOOLEAN IsNameValueType,
1535 IN EFI_HII_HANDLE HiiHandle
1536 )
1537{
1538 LIST_ENTRY *Link;
1539 IFR_BLOCK_DATA *BlockData;
1540 EFI_STRING Name;
1541
1542 //
1543 // No Request Block array, all vars are got.
1544 //
1545 if (RequestBlockArray == NULL) {
1546 return TRUE;
1547 }
1548
1549 //
1550 // Check the input var is in the request block range.
1551 //
1552 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
1553 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1554
1555 if (IsNameValueType) {
1556 Name = InternalGetString (HiiHandle, VarOffset);
1557 ASSERT (Name != NULL);
1558
1559 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
1560 FreePool (Name);
1561 return TRUE;
1562 }
1563
1564 FreePool (Name);
1565 } else {
1566 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
1567 return TRUE;
1568 }
1569 }
1570 }
1571
1572 return FALSE;
1573}
1574
1583EFI_STATUS
1585 IN HII_DATABASE_RECORD *DataBaseRecord,
1586 IN OUT UINT8 **HiiFormPackage,
1587 OUT UINTN *PackageSize
1588 )
1589{
1590 EFI_STATUS Status;
1591 UINTN Size;
1592 UINTN ResultSize;
1593
1594 if ((DataBaseRecord == NULL) || (HiiFormPackage == NULL) || (PackageSize == NULL)) {
1595 return EFI_INVALID_PARAMETER;
1596 }
1597
1598 Size = 0;
1599 ResultSize = 0;
1600 //
1601 // 0. Get Hii Form Package by HiiHandle
1602 //
1603 Status = ExportFormPackages (
1604 &mPrivate,
1605 DataBaseRecord->Handle,
1606 DataBaseRecord->PackageList,
1607 0,
1608 Size,
1609 HiiFormPackage,
1610 &ResultSize
1611 );
1612 if (EFI_ERROR (Status)) {
1613 return Status;
1614 }
1615
1616 (*HiiFormPackage) = AllocatePool (ResultSize);
1617 if (*HiiFormPackage == NULL) {
1618 Status = EFI_OUT_OF_RESOURCES;
1619 return Status;
1620 }
1621
1622 //
1623 // Get HiiFormPackage by HiiHandle
1624 //
1625 Size = ResultSize;
1626 ResultSize = 0;
1627 Status = ExportFormPackages (
1628 &mPrivate,
1629 DataBaseRecord->Handle,
1630 DataBaseRecord->PackageList,
1631 0,
1632 Size,
1633 *HiiFormPackage,
1634 &ResultSize
1635 );
1636 if (EFI_ERROR (Status)) {
1637 FreePool (*HiiFormPackage);
1638 }
1639
1640 *PackageSize = Size;
1641
1642 return Status;
1643}
1644
1654EFI_STATUS
1656 IN HII_DATABASE_RECORD *DataBaseRecord,
1657 IN EFI_STRING ConfigHdr,
1658 OUT BOOLEAN *IsEfiVarstore,
1659 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
1660 )
1661{
1662 EFI_STATUS Status;
1663 UINTN IfrOffset;
1664 UINTN PackageOffset;
1665 EFI_IFR_OP_HEADER *IfrOpHdr;
1666 CHAR16 *VarStoreName;
1667 UINTN NameSize;
1668 EFI_STRING GuidStr;
1669 EFI_STRING NameStr;
1670 EFI_STRING TempStr;
1671 UINTN LengthString;
1672 UINT8 *HiiFormPackage;
1673 UINTN PackageSize;
1674 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1675 EFI_HII_PACKAGE_HEADER *PackageHeader;
1676
1677 HiiFormPackage = NULL;
1678 LengthString = 0;
1679 Status = EFI_SUCCESS;
1680 GuidStr = NULL;
1681 NameStr = NULL;
1682 TempStr = NULL;
1683 *IsEfiVarstore = FALSE;
1684
1685 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
1686 if (EFI_ERROR (Status)) {
1687 return Status;
1688 }
1689
1690 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1691 PackageOffset = IfrOffset;
1692 PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
1693
1694 while (IfrOffset < PackageSize) {
1695 //
1696 // More than one form packages exist.
1697 //
1698 if (PackageOffset >= PackageHeader->Length) {
1699 //
1700 // Process the new form package.
1701 //
1702 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1703 IfrOffset += PackageOffset;
1704 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
1705 }
1706
1707 IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
1708 IfrOffset += IfrOpHdr->Length;
1709 PackageOffset += IfrOpHdr->Length;
1710
1711 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1712 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
1713 //
1714 // If the length is small than the structure, this is from old efi
1715 // varstore definition. Old efi varstore get config directly from
1716 // GetVariable function.
1717 //
1718 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1719 continue;
1720 }
1721
1722 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1723 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1724 if (VarStoreName == NULL) {
1725 Status = EFI_OUT_OF_RESOURCES;
1726 goto Done;
1727 }
1728
1729 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
1730
1731 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&IfrEfiVarStore->Guid, 1, &GuidStr);
1732 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *)VarStoreName, 2, &NameStr);
1733 LengthString = StrLen (GuidStr);
1734 LengthString = LengthString + StrLen (NameStr) + 1;
1735 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1736 if (TempStr == NULL) {
1737 FreePool (GuidStr);
1738 FreePool (NameStr);
1739 FreePool (VarStoreName);
1740 Status = EFI_OUT_OF_RESOURCES;
1741 goto Done;
1742 }
1743
1744 StrCpyS (TempStr, LengthString, GuidStr);
1745 StrCatS (TempStr, LengthString, NameStr);
1746 if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
1747 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *)AllocateZeroPool (IfrOpHdr->Length);
1748 if (*EfiVarStore == NULL) {
1749 FreePool (VarStoreName);
1750 FreePool (GuidStr);
1751 FreePool (NameStr);
1752 FreePool (TempStr);
1753 Status = EFI_OUT_OF_RESOURCES;
1754 goto Done;
1755 }
1756
1757 *IsEfiVarstore = TRUE;
1758 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1759 }
1760
1761 //
1762 // Free allocated temp string.
1763 //
1764 FreePool (VarStoreName);
1765 FreePool (GuidStr);
1766 FreePool (NameStr);
1767 FreePool (TempStr);
1768
1769 //
1770 // Already found the varstore, break;
1771 //
1772 if (*IsEfiVarstore) {
1773 break;
1774 }
1775 }
1776 }
1777
1778Done:
1779 if (HiiFormPackage != NULL) {
1780 FreePool (HiiFormPackage);
1781 }
1782
1783 return Status;
1784}
1785
1797BOOLEAN
1799 IN EFI_STRING ConfigRequest
1800 )
1801{
1802 EFI_STRING TmpRequest;
1803
1804 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1805 ASSERT (TmpRequest != NULL);
1806
1807 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1808 return TRUE;
1809 }
1810
1811 return FALSE;
1812}
1813
1825BOOLEAN
1827 IN EFI_GUID *VarstoreGuid,
1828 IN CHAR16 *Name,
1829 IN CHAR16 *ConfigHdr
1830 )
1831{
1832 EFI_STRING GuidStr;
1833 EFI_STRING NameStr;
1834 EFI_STRING TempStr;
1835 UINTN LengthString;
1836 BOOLEAN RetVal;
1837
1838 RetVal = FALSE;
1839 GuidStr = NULL;
1840 TempStr = NULL;
1841
1842 //
1843 // If ConfigHdr has name field and varstore not has name, return FALSE.
1844 //
1845 if ((Name == NULL) && (ConfigHdr != NULL) && (StrStr (ConfigHdr, L"NAME=&") == NULL)) {
1846 return FALSE;
1847 }
1848
1849 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1850 if (Name != NULL) {
1851 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
1852 } else {
1853 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1854 }
1855
1856 LengthString = StrLen (GuidStr);
1857 LengthString = LengthString + StrLen (NameStr) + 1;
1858 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1859 if (TempStr == NULL) {
1860 goto Done;
1861 }
1862
1863 StrCpyS (TempStr, LengthString, GuidStr);
1864 StrCatS (TempStr, LengthString, NameStr);
1865
1866 if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
1867 RetVal = TRUE;
1868 }
1869
1870Done:
1871 if (GuidStr != NULL) {
1872 FreePool (GuidStr);
1873 }
1874
1875 if (NameStr != NULL) {
1876 FreePool (NameStr);
1877 }
1878
1879 if (TempStr != NULL) {
1880 FreePool (TempStr);
1881 }
1882
1883 return RetVal;
1884}
1885
1895BOOLEAN
1897 IN HII_DATABASE_RECORD *DataBaseRecord,
1898 IN EFI_STRING ConfigHdr
1899 )
1900{
1901 EFI_STATUS Status;
1902 UINTN IfrOffset;
1903 UINTN PackageOffset;
1904 EFI_IFR_OP_HEADER *IfrOpHdr;
1905 CHAR16 *VarStoreName;
1906 UINTN NameSize;
1907 UINT8 *HiiFormPackage;
1908 UINTN PackageSize;
1909 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1910 EFI_HII_PACKAGE_HEADER *PackageHeader;
1911 EFI_IFR_VARSTORE *IfrVarStore;
1912 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1913 BOOLEAN FindVarstore;
1914
1915 HiiFormPackage = NULL;
1916 VarStoreName = NULL;
1917 Status = EFI_SUCCESS;
1918 FindVarstore = FALSE;
1919
1920 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
1921 if (EFI_ERROR (Status)) {
1922 return FALSE;
1923 }
1924
1925 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1926 PackageOffset = IfrOffset;
1927 PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
1928
1929 while (IfrOffset < PackageSize) {
1930 //
1931 // More than one form packages exist.
1932 //
1933 if (PackageOffset >= PackageHeader->Length) {
1934 //
1935 // Process the new form package.
1936 //
1937 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1938 IfrOffset += PackageOffset;
1939 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
1940 }
1941
1942 IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
1943 IfrOffset += IfrOpHdr->Length;
1944 PackageOffset += IfrOpHdr->Length;
1945
1946 switch (IfrOpHdr->OpCode) {
1947 case EFI_IFR_VARSTORE_OP:
1948 IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
1949
1950 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
1951 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1952 if (VarStoreName == NULL) {
1953 goto Done;
1954 }
1955
1956 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
1957
1958 if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1959 FindVarstore = TRUE;
1960 goto Done;
1961 } else {
1962 FreePool (VarStoreName);
1963 VarStoreName = NULL;
1964 }
1965
1966 break;
1967
1968 case EFI_IFR_VARSTORE_EFI_OP:
1969 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
1970 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1971 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1972 if (VarStoreName == NULL) {
1973 goto Done;
1974 }
1975
1976 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
1977
1978 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1979 FindVarstore = TRUE;
1980 goto Done;
1981 } else {
1982 FreePool (VarStoreName);
1983 VarStoreName = NULL;
1984 }
1985
1986 break;
1987
1988 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1989 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
1990
1991 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1992 FindVarstore = TRUE;
1993 goto Done;
1994 }
1995
1996 break;
1997
1998 case EFI_IFR_FORM_OP:
1999 case EFI_IFR_FORM_MAP_OP:
2000 //
2001 // No matched varstore is found and directly return.
2002 //
2003 goto Done;
2004
2005 default:
2006 break;
2007 }
2008 }
2009
2010Done:
2011 if (HiiFormPackage != NULL) {
2012 FreePool (HiiFormPackage);
2013 }
2014
2015 if (VarStoreName != NULL) {
2016 FreePool (VarStoreName);
2017 }
2018
2019 return FindVarstore;
2020}
2021
2038EFI_STATUS
2040 IN IFR_BLOCK_DATA *RequestBlockArray,
2041 IN EFI_HII_HANDLE HiiHandle,
2042 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
2043 IN EFI_IFR_OP_HEADER *IfrOpHdr,
2044 IN UINT16 VarWidth,
2045 OUT IFR_BLOCK_DATA **ReturnData,
2046 IN BOOLEAN IsBitVar
2047 )
2048{
2049 IFR_BLOCK_DATA *BlockData;
2050 UINT16 VarOffset;
2051 EFI_STRING_ID NameId;
2052 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
2053 UINT16 BitOffset;
2054 UINT16 BitWidth;
2055 UINT16 TotalBits;
2056
2057 NameId = 0;
2058 VarOffset = 0;
2059 BitOffset = 0;
2060 BitWidth = 0;
2061 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
2062
2063 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2064 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
2065
2066 //
2067 // Check whether this question is in requested block array.
2068 //
2069 if (!InternalBlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
2070 //
2071 // This question is not in the requested string. Skip it.
2072 //
2073 return EFI_NOT_FOUND;
2074 }
2075 } else {
2076 //
2077 // Get the byte offset/with and bit offset/width
2078 //
2079 if (IsBitVar) {
2080 BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
2081 BitWidth = VarWidth;
2082 VarOffset = BitOffset / 8;
2083 //
2084 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
2085 //
2086 TotalBits = BitOffset % 8 + BitWidth;
2087 VarWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
2088 } else {
2089 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
2090 BitWidth = VarWidth;
2091 BitOffset = VarOffset * 8;
2092 }
2093
2094 //
2095 // Check whether this question is in requested block array.
2096 //
2097 if (!InternalBlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
2098 //
2099 // This question is not in the requested string. Skip it.
2100 //
2101 return EFI_NOT_FOUND;
2102 }
2103
2104 //
2105 // Check this var question is in the var storage
2106 //
2107 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
2108 return EFI_INVALID_PARAMETER;
2109 }
2110 }
2111
2112 BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2113 if (BlockData == NULL) {
2114 return EFI_OUT_OF_RESOURCES;
2115 }
2116
2117 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2118 BlockData->Name = InternalGetString (HiiHandle, NameId);
2119 } else {
2120 BlockData->Offset = VarOffset;
2121 }
2122
2123 BlockData->Width = VarWidth;
2124 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
2125 BlockData->OpCode = IfrOpHdr->OpCode;
2126 BlockData->Scope = IfrOpHdr->Scope;
2127 BlockData->IsBitVar = IsBitVar;
2128 BlockData->BitOffset = BitOffset;
2129 BlockData->BitWidth = BitWidth;
2130 InitializeListHead (&BlockData->DefaultValueEntry);
2131 //
2132 // Add Block Data into VarStorageData BlockEntry
2133 //
2134 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2135 *ReturnData = BlockData;
2136
2137 return EFI_SUCCESS;
2138}
2139
2158EFI_STATUS
2159EFIAPI
2161 IN EFI_HII_HANDLE HiiHandle,
2162 IN UINT8 *Package,
2163 IN UINT32 PackageLength,
2164 IN EFI_STRING ConfigHdr,
2165 IN IFR_BLOCK_DATA *RequestBlockArray,
2166 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
2167 OUT IFR_DEFAULT_DATA *DefaultIdArray
2168 )
2169{
2170 EFI_STATUS Status;
2171 UINTN IfrOffset;
2172 UINTN PackageOffset;
2173 EFI_IFR_VARSTORE *IfrVarStore;
2174 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
2175 EFI_IFR_OP_HEADER *IfrOpHdr;
2176 EFI_IFR_ONE_OF *IfrOneOf;
2177 EFI_IFR_REF4 *IfrRef;
2178 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
2179 EFI_IFR_DEFAULT *IfrDefault;
2180 EFI_IFR_ORDERED_LIST *IfrOrderedList;
2181 EFI_IFR_CHECKBOX *IfrCheckBox;
2182 EFI_IFR_PASSWORD *IfrPassword;
2183 EFI_IFR_STRING *IfrString;
2184 EFI_IFR_DATE *IfrDate;
2185 EFI_IFR_TIME *IfrTime;
2186 IFR_DEFAULT_DATA DefaultData;
2187 IFR_DEFAULT_DATA *DefaultDataPtr;
2188 IFR_BLOCK_DATA *BlockData;
2189 CHAR16 *VarStoreName;
2190 UINTN NameSize;
2191 UINT16 VarWidth;
2192 UINT16 VarDefaultId;
2193 BOOLEAN FirstOneOfOption;
2194 BOOLEAN FirstOrderedList;
2195 LIST_ENTRY *LinkData;
2196 LIST_ENTRY *LinkDefault;
2197 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
2198 EFI_HII_PACKAGE_HEADER *PackageHeader;
2199 EFI_VARSTORE_ID VarStoreId;
2200 UINT16 SmallestDefaultId;
2201 BOOLEAN SmallestIdFromFlag;
2202 BOOLEAN FromOtherDefaultOpcode;
2203 BOOLEAN QuestionReferBitField;
2204
2205 Status = EFI_SUCCESS;
2206 BlockData = NULL;
2207 DefaultDataPtr = NULL;
2208 FirstOneOfOption = FALSE;
2209 VarStoreId = 0;
2210 FirstOrderedList = FALSE;
2211 VarStoreName = NULL;
2212 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
2213 SmallestDefaultId = 0xFFFF;
2214 FromOtherDefaultOpcode = FALSE;
2215 QuestionReferBitField = FALSE;
2216
2217 //
2218 // Go through the form package to parse OpCode one by one.
2219 //
2220 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2221 PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
2222 IfrOffset = PackageOffset;
2223 while (IfrOffset < PackageLength) {
2224 //
2225 // More than one form package found.
2226 //
2227 if (PackageOffset >= PackageHeader->Length) {
2228 //
2229 // Already found varstore for this request, break;
2230 //
2231 if (VarStoreId != 0) {
2232 VarStoreId = 0;
2233 }
2234
2235 //
2236 // Get next package header info.
2237 //
2238 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
2239 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2240 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(Package + IfrOffset);
2241 }
2242
2243 IfrOpHdr = (EFI_IFR_OP_HEADER *)(Package + IfrOffset);
2244 switch (IfrOpHdr->OpCode) {
2245 case EFI_IFR_VARSTORE_OP:
2246 //
2247 // VarStore is found. Don't need to search any more.
2248 //
2249 if (VarStoreId != 0) {
2250 break;
2251 }
2252
2253 IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
2254
2255 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
2256 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2257 if (VarStoreName == NULL) {
2258 Status = EFI_OUT_OF_RESOURCES;
2259 goto Done;
2260 }
2261
2262 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
2263
2264 if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
2265 //
2266 // Find the matched VarStore
2267 //
2268 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrVarStore->Guid);
2269 VarStorageData->Size = IfrVarStore->Size;
2270 VarStorageData->Name = VarStoreName;
2271 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
2272 VarStoreId = IfrVarStore->VarStoreId;
2273 } else {
2274 FreePool (VarStoreName);
2275 VarStoreName = NULL;
2276 }
2277
2278 break;
2279
2280 case EFI_IFR_VARSTORE_EFI_OP:
2281 //
2282 // VarStore is found. Don't need to search any more.
2283 //
2284 if (VarStoreId != 0) {
2285 break;
2286 }
2287
2288 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
2289
2290 //
2291 // If the length is small than the structure, this is from old efi
2292 // varstore definition. Old efi varstore get config directly from
2293 // GetVariable function.
2294 //
2295 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
2296 break;
2297 }
2298
2299 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
2300 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2301 if (VarStoreName == NULL) {
2302 Status = EFI_OUT_OF_RESOURCES;
2303 goto Done;
2304 }
2305
2306 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
2307
2308 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
2309 //
2310 // Find the matched VarStore
2311 //
2312 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrEfiVarStore->Guid);
2313 VarStorageData->Size = IfrEfiVarStore->Size;
2314 VarStorageData->Name = VarStoreName;
2315 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
2316 VarStoreId = IfrEfiVarStore->VarStoreId;
2317 } else {
2318 FreePool (VarStoreName);
2319 VarStoreName = NULL;
2320 }
2321
2322 break;
2323
2324 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
2325 //
2326 // VarStore is found. Don't need to search any more.
2327 //
2328 if (VarStoreId != 0) {
2329 break;
2330 }
2331
2332 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
2333
2334 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
2335 //
2336 // Find the matched VarStore
2337 //
2338 CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrNameValueVarStore->Guid);
2339 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
2340 VarStoreId = IfrNameValueVarStore->VarStoreId;
2341 }
2342
2343 break;
2344
2345 case EFI_IFR_DEFAULTSTORE_OP:
2346 //
2347 // Add new the map between default id and default name.
2348 //
2349 DefaultDataPtr = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
2350 if (DefaultDataPtr == NULL) {
2351 Status = EFI_OUT_OF_RESOURCES;
2352 goto Done;
2353 }
2354
2355 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
2356 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
2357 DefaultDataPtr = NULL;
2358 break;
2359
2360 case EFI_IFR_FORM_OP:
2361 case EFI_IFR_FORM_MAP_OP:
2362 //
2363 // No matched varstore is found and directly return.
2364 //
2365 if ( VarStoreId == 0) {
2366 Status = EFI_SUCCESS;
2367 goto Done;
2368 }
2369
2370 break;
2371
2372 case EFI_IFR_REF_OP:
2373 //
2374 // Ref question is not in IFR Form. This IFR form is not valid.
2375 //
2376 if ( VarStoreId == 0) {
2377 Status = EFI_INVALID_PARAMETER;
2378 goto Done;
2379 }
2380
2381 //
2382 // Check whether this question is for the requested varstore.
2383 //
2384 IfrRef = (EFI_IFR_REF4 *)IfrOpHdr;
2385 if (IfrRef->Question.VarStoreId != VarStoreId) {
2386 break;
2387 }
2388
2389 VarWidth = (UINT16)(sizeof (EFI_HII_REF));
2390
2391 //
2392 // The BlockData may allocate by other opcode,need to clean.
2393 //
2394 if (BlockData != NULL) {
2395 BlockData = NULL;
2396 }
2397
2398 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2399 if (EFI_ERROR (Status)) {
2400 if (Status == EFI_NOT_FOUND) {
2401 //
2402 // The opcode is not required,exit and parse other opcode.
2403 //
2404 break;
2405 }
2406
2407 goto Done;
2408 }
2409
2410 break;
2411
2412 case EFI_IFR_ONE_OF_OP:
2413 case EFI_IFR_NUMERIC_OP:
2414 //
2415 // Numeric and OneOf has the same opcode structure.
2416 //
2417
2418 //
2419 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2420 //
2421 if (VarStoreId == 0) {
2422 Status = EFI_INVALID_PARAMETER;
2423 goto Done;
2424 }
2425
2426 //
2427 // Check whether this question is for the requested varstore.
2428 //
2429 IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpHdr;
2430 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
2431 break;
2432 }
2433
2434 if (QuestionReferBitField) {
2435 VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
2436 } else {
2437 VarWidth = (UINT16)(1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
2438 }
2439
2440 //
2441 // The BlockData may allocate by other opcode,need to clean.
2442 //
2443 if (BlockData != NULL) {
2444 BlockData = NULL;
2445 }
2446
2447 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
2448 if (EFI_ERROR (Status)) {
2449 if (Status == EFI_NOT_FOUND) {
2450 //
2451 // The opcode is not required,exit and parse other opcode.
2452 //
2453 break;
2454 }
2455
2456 goto Done;
2457 }
2458
2459 //
2460 // when go to there,BlockData can't be NULLL.
2461 //
2462 ASSERT (BlockData != NULL);
2463
2464 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
2465 //
2466 // Set this flag to TRUE for the first oneof option.
2467 //
2468 FirstOneOfOption = TRUE;
2469 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
2470 //
2471 // Numeric minimum value will be used as default value when no default is specified.
2472 //
2473 DefaultData.Type = DefaultValueFromDefault;
2474 if (QuestionReferBitField) {
2475 //
2476 // Since default value in bit field was stored as UINT32 type.
2477 //
2478 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
2479 } else {
2480 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
2481 case EFI_IFR_NUMERIC_SIZE_1:
2482 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
2483 break;
2484
2485 case EFI_IFR_NUMERIC_SIZE_2:
2486 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
2487 break;
2488
2489 case EFI_IFR_NUMERIC_SIZE_4:
2490 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
2491 break;
2492
2493 case EFI_IFR_NUMERIC_SIZE_8:
2494 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
2495 break;
2496
2497 default:
2498 Status = EFI_INVALID_PARAMETER;
2499 goto Done;
2500 }
2501 }
2502
2503 //
2504 // Set default value base on the DefaultId list get from IFR data.
2505 //
2506 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2507 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2508 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2509 InsertDefaultValue (BlockData, &DefaultData);
2510 }
2511 }
2512
2513 break;
2514
2515 case EFI_IFR_ORDERED_LIST_OP:
2516 //
2517 // offset by question header
2518 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2519 //
2520
2521 FirstOrderedList = TRUE;
2522 //
2523 // OrderedList question is not in IFR Form. This IFR form is not valid.
2524 //
2525 if (VarStoreId == 0) {
2526 Status = EFI_INVALID_PARAMETER;
2527 goto Done;
2528 }
2529
2530 //
2531 // Check whether this question is for the requested varstore.
2532 //
2533 IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpHdr;
2534 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
2535 BlockData = NULL;
2536 break;
2537 }
2538
2539 VarWidth = IfrOrderedList->MaxContainers;
2540
2541 //
2542 // The BlockData may allocate by other opcode,need to clean.
2543 //
2544 if (BlockData != NULL) {
2545 BlockData = NULL;
2546 }
2547
2548 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2549 if (EFI_ERROR (Status)) {
2550 if (Status == EFI_NOT_FOUND) {
2551 //
2552 // The opcode is not required,exit and parse other opcode.
2553 //
2554 break;
2555 }
2556
2557 goto Done;
2558 }
2559
2560 break;
2561
2562 case EFI_IFR_CHECKBOX_OP:
2563 //
2564 // EFI_IFR_DEFAULT_OP
2565 // offset by question header
2566 // width is 1 sizeof (BOOLEAN)
2567 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2568 // value by DefaultOption
2569 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2570 //
2571
2572 //
2573 // CheckBox question is not in IFR Form. This IFR form is not valid.
2574 //
2575 if (VarStoreId == 0) {
2576 Status = EFI_INVALID_PARAMETER;
2577 goto Done;
2578 }
2579
2580 //
2581 // Check whether this question is for the requested varstore.
2582 //
2583 IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
2584 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
2585 break;
2586 }
2587
2588 VarWidth = (UINT16)sizeof (BOOLEAN);
2589
2590 //
2591 // The BlockData may allocate by other opcode,need to clean.
2592 //
2593 if (BlockData != NULL) {
2594 BlockData = NULL;
2595 }
2596
2597 if (QuestionReferBitField) {
2598 VarWidth = 1;
2599 }
2600
2601 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
2602 if (EFI_ERROR (Status)) {
2603 if (Status == EFI_NOT_FOUND) {
2604 //
2605 // The opcode is not required,exit and parse other opcode.
2606 //
2607 break;
2608 }
2609
2610 goto Done;
2611 }
2612
2613 //
2614 // when go to there,BlockData can't be NULLL.
2615 //
2616 ASSERT (BlockData != NULL);
2617
2618 SmallestIdFromFlag = FALSE;
2619
2620 //
2621 // Add default value for standard ID by CheckBox Flag
2622 //
2623 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2624 //
2625 // Prepare new DefaultValue
2626 //
2627 DefaultData.DefaultId = VarDefaultId;
2628 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
2629 //
2630 // When flag is set, default value is TRUE.
2631 //
2632 DefaultData.Type = DefaultValueFromFlag;
2633 if (QuestionReferBitField) {
2634 DefaultData.Value.u32 = TRUE;
2635 } else {
2636 DefaultData.Value.b = TRUE;
2637 }
2638
2639 InsertDefaultValue (BlockData, &DefaultData);
2640
2641 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
2642 //
2643 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2644 //
2645 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2646 SmallestIdFromFlag = TRUE;
2647 }
2648 }
2649
2650 //
2651 // Add default value for Manufacture ID by CheckBox Flag
2652 //
2653 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2654 //
2655 // Prepare new DefaultValue
2656 //
2657 DefaultData.DefaultId = VarDefaultId;
2658 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
2659 //
2660 // When flag is set, default value is TRUE.
2661 //
2662 DefaultData.Type = DefaultValueFromFlag;
2663 if (QuestionReferBitField) {
2664 DefaultData.Value.u32 = TRUE;
2665 } else {
2666 DefaultData.Value.b = TRUE;
2667 }
2668
2669 InsertDefaultValue (BlockData, &DefaultData);
2670
2671 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2672 //
2673 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2674 //
2675 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2676 SmallestIdFromFlag = TRUE;
2677 }
2678 }
2679
2680 if (SmallestIdFromFlag) {
2681 //
2682 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2683 //
2684 DefaultData.Type = DefaultValueFromOtherDefault;
2685 if (QuestionReferBitField) {
2686 DefaultData.Value.u32 = TRUE;
2687 } else {
2688 DefaultData.Value.b = TRUE;
2689 }
2690
2691 //
2692 // Set default value for all the default id in the DefaultId list.
2693 //
2694 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2695 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2696 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2697 InsertDefaultValue (BlockData, &DefaultData);
2698 }
2699 } else {
2700 //
2701 // When flag is not set, default value is FASLE.
2702 //
2703 DefaultData.Type = DefaultValueFromDefault;
2704 if (QuestionReferBitField) {
2705 DefaultData.Value.u32 = FALSE;
2706 } else {
2707 DefaultData.Value.b = FALSE;
2708 }
2709
2710 //
2711 // Set default value for all the default id in the DefaultId list.
2712 //
2713 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2714 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2715 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2716 InsertDefaultValue (BlockData, &DefaultData);
2717 }
2718 }
2719
2720 break;
2721
2722 case EFI_IFR_DATE_OP:
2723 //
2724 // offset by question header
2725 // width MaxSize * sizeof (CHAR16)
2726 // no default value, only block array
2727 //
2728
2729 //
2730 // Date question is not in IFR Form. This IFR form is not valid.
2731 //
2732 if (VarStoreId == 0) {
2733 Status = EFI_INVALID_PARAMETER;
2734 goto Done;
2735 }
2736
2737 //
2738 // Check whether this question is for the requested varstore.
2739 //
2740 IfrDate = (EFI_IFR_DATE *)IfrOpHdr;
2741 if (IfrDate->Question.VarStoreId != VarStoreId) {
2742 break;
2743 }
2744
2745 //
2746 // The BlockData may allocate by other opcode,need to clean.
2747 //
2748 if (BlockData != NULL) {
2749 BlockData = NULL;
2750 }
2751
2752 VarWidth = (UINT16)sizeof (EFI_HII_DATE);
2753 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2754 if (EFI_ERROR (Status)) {
2755 if (Status == EFI_NOT_FOUND) {
2756 //
2757 // The opcode is not required,exit and parse other opcode.
2758 //
2759 break;
2760 }
2761
2762 goto Done;
2763 }
2764
2765 break;
2766
2767 case EFI_IFR_TIME_OP:
2768 //
2769 // offset by question header
2770 // width MaxSize * sizeof (CHAR16)
2771 // no default value, only block array
2772 //
2773
2774 //
2775 // Time question is not in IFR Form. This IFR form is not valid.
2776 //
2777 if (VarStoreId == 0) {
2778 Status = EFI_INVALID_PARAMETER;
2779 goto Done;
2780 }
2781
2782 //
2783 // Check whether this question is for the requested varstore.
2784 //
2785 IfrTime = (EFI_IFR_TIME *)IfrOpHdr;
2786 if (IfrTime->Question.VarStoreId != VarStoreId) {
2787 break;
2788 }
2789
2790 //
2791 // The BlockData may allocate by other opcode,need to clean.
2792 //
2793 if (BlockData != NULL) {
2794 BlockData = NULL;
2795 }
2796
2797 VarWidth = (UINT16)sizeof (EFI_HII_TIME);
2798 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2799 if (EFI_ERROR (Status)) {
2800 if (Status == EFI_NOT_FOUND) {
2801 //
2802 // The opcode is not required,exit and parse other opcode.
2803 //
2804 break;
2805 }
2806
2807 goto Done;
2808 }
2809
2810 break;
2811
2812 case EFI_IFR_STRING_OP:
2813 //
2814 // offset by question header
2815 // width MaxSize * sizeof (CHAR16)
2816 // no default value, only block array
2817 //
2818
2819 //
2820 // String question is not in IFR Form. This IFR form is not valid.
2821 //
2822 if (VarStoreId == 0) {
2823 Status = EFI_INVALID_PARAMETER;
2824 goto Done;
2825 }
2826
2827 //
2828 // Check whether this question is for the requested varstore.
2829 //
2830 IfrString = (EFI_IFR_STRING *)IfrOpHdr;
2831 if (IfrString->Question.VarStoreId != VarStoreId) {
2832 break;
2833 }
2834
2835 //
2836 // The BlockData may allocate by other opcode,need to clean.
2837 //
2838 if (BlockData != NULL) {
2839 BlockData = NULL;
2840 }
2841
2842 VarWidth = (UINT16)(IfrString->MaxSize * sizeof (UINT16));
2843 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2844 if (EFI_ERROR (Status)) {
2845 if (Status == EFI_NOT_FOUND) {
2846 //
2847 // The opcode is not required,exit and parse other opcode.
2848 //
2849 break;
2850 }
2851
2852 goto Done;
2853 }
2854
2855 break;
2856
2857 case EFI_IFR_PASSWORD_OP:
2858 //
2859 // offset by question header
2860 // width MaxSize * sizeof (CHAR16)
2861 // no default value, only block array
2862 //
2863
2864 //
2865 // Password question is not in IFR Form. This IFR form is not valid.
2866 //
2867 if (VarStoreId == 0) {
2868 Status = EFI_INVALID_PARAMETER;
2869 goto Done;
2870 }
2871
2872 //
2873 // Check whether this question is for the requested varstore.
2874 //
2875 IfrPassword = (EFI_IFR_PASSWORD *)IfrOpHdr;
2876 if (IfrPassword->Question.VarStoreId != VarStoreId) {
2877 break;
2878 }
2879
2880 //
2881 // The BlockData may allocate by other opcode,need to clean.
2882 //
2883 if (BlockData != NULL) {
2884 BlockData = NULL;
2885 }
2886
2887 VarWidth = (UINT16)(IfrPassword->MaxSize * sizeof (UINT16));
2888 Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
2889 if (EFI_ERROR (Status)) {
2890 if (Status == EFI_NOT_FOUND) {
2891 //
2892 // The opcode is not required,exit and parse other opcode.
2893 //
2894 break;
2895 }
2896
2897 goto Done;
2898 }
2899
2900 //
2901 // No default value for string.
2902 //
2903 BlockData = NULL;
2904 break;
2905
2906 case EFI_IFR_ONE_OF_OPTION_OP:
2907 //
2908 // No matched block data is ignored.
2909 //
2910 if ((BlockData == NULL) || (BlockData->Scope == 0)) {
2911 break;
2912 }
2913
2914 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
2915 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2916 if (!FirstOrderedList) {
2917 break;
2918 }
2919
2920 //
2921 // Get ordered list option data type.
2922 //
2923 if ((IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN)) {
2924 VarWidth = 1;
2925 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
2926 VarWidth = 2;
2927 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
2928 VarWidth = 4;
2929 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
2930 VarWidth = 8;
2931 } else {
2932 //
2933 // Invalid ordered list option data type.
2934 //
2935 Status = EFI_INVALID_PARAMETER;
2936 if (BlockData->Name != NULL) {
2937 FreePool (BlockData->Name);
2938 }
2939
2940 FreePool (BlockData);
2941 goto Done;
2942 }
2943
2944 //
2945 // Calculate Ordered list QuestionId width.
2946 //
2947 BlockData->Width = (UINT16)(BlockData->Width * VarWidth);
2948 //
2949 // Check whether this question is in requested block array.
2950 //
2951 if (!InternalBlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2952 //
2953 // This question is not in the requested string. Skip it.
2954 //
2955 if (BlockData->Name != NULL) {
2956 FreePool (BlockData->Name);
2957 }
2958
2959 FreePool (BlockData);
2960 BlockData = NULL;
2961 break;
2962 }
2963
2964 //
2965 // Check this var question is in the var storage
2966 //
2967 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2968 Status = EFI_INVALID_PARAMETER;
2969 if (BlockData->Name != NULL) {
2970 FreePool (BlockData->Name);
2971 }
2972
2973 FreePool (BlockData);
2974 goto Done;
2975 }
2976
2977 //
2978 // Add Block Data into VarStorageData BlockEntry
2979 //
2980 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2981
2982 FirstOrderedList = FALSE;
2983
2984 break;
2985 }
2986
2987 //
2988 // 1. Set default value for OneOf option when flag field has default attribute.
2989 // And set the default value with the smallest default id for other default id in the DefaultId list.
2990 //
2991 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2992 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))
2993 {
2994 //
2995 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2996 // The first oneof option value will be used as default value when no default value is specified.
2997 //
2998 FirstOneOfOption = FALSE;
2999
3000 SmallestIdFromFlag = FALSE;
3001
3002 // Prepare new DefaultValue
3003 //
3004 DefaultData.Type = DefaultValueFromFlag;
3005 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
3006 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
3007 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
3008 InsertDefaultValue (BlockData, &DefaultData);
3009 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
3010 //
3011 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3012 //
3013 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
3014 SmallestIdFromFlag = TRUE;
3015 }
3016 }
3017
3018 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
3019 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
3020 InsertDefaultValue (BlockData, &DefaultData);
3021 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
3022 //
3023 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3024 //
3025 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
3026 SmallestIdFromFlag = TRUE;
3027 }
3028 }
3029
3030 if (SmallestIdFromFlag) {
3031 //
3032 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
3033 //
3034 DefaultData.Type = DefaultValueFromOtherDefault;
3035 //
3036 // Set default value for other default id in the DefaultId list.
3037 //
3038 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
3039 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
3040 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
3041 InsertDefaultValue (BlockData, &DefaultData);
3042 }
3043 }
3044 }
3045
3046 //
3047 // 2. Set as the default value when this is the first option.
3048 // The first oneof option value will be used as default value when no default value is specified.
3049 //
3050 if (FirstOneOfOption) {
3051 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
3052 FirstOneOfOption = FALSE;
3053
3054 //
3055 // Prepare new DefaultValue
3056 //
3057 DefaultData.Type = DefaultValueFromDefault;
3058 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
3059 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
3060 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
3061 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
3062 InsertDefaultValue (BlockData, &DefaultData);
3063 }
3064 }
3065
3066 break;
3067
3068 case EFI_IFR_DEFAULT_OP:
3069 //
3070 // Update Current BlockData to the default value.
3071 //
3072 if ((BlockData == NULL) || (BlockData->Scope == 0)) {
3073 //
3074 // No matched block data is ignored.
3075 //
3076 break;
3077 }
3078
3079 //
3080 // Get the DefaultId
3081 //
3082 IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
3083 VarDefaultId = IfrDefault->DefaultId;
3084 //
3085 // Prepare new DefaultValue
3086 //
3087 DefaultData.Type = DefaultValueFromOpcode;
3088 DefaultData.DefaultId = VarDefaultId;
3089 if (QuestionReferBitField) {
3090 CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));
3091 } else {
3092 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
3093 }
3094
3095 // If the value field is expression, set the cleaned flag.
3096 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
3097 DefaultData.Cleaned = TRUE;
3098 }
3099
3100 //
3101 // Add DefaultValue into current BlockData
3102 //
3103 InsertDefaultValue (BlockData, &DefaultData);
3104
3105 //
3106 // Set default value for other default id in the DefaultId list.
3107 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3108 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3109 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3110 //
3111 if ((SmallestDefaultId > VarDefaultId) || ((SmallestDefaultId == VarDefaultId) && !FromOtherDefaultOpcode)) {
3112 FromOtherDefaultOpcode = TRUE;
3113 SmallestDefaultId = VarDefaultId;
3114 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
3115 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
3116 if (DefaultDataPtr->DefaultId != DefaultData.DefaultId) {
3117 DefaultData.Type = DefaultValueFromOtherDefault;
3118 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
3119 InsertDefaultValue (BlockData, &DefaultData);
3120 }
3121 }
3122 }
3123
3124 //
3125 // After insert the default value, reset the cleaned value for next
3126 // time used. If not set here, need to set the value before every time.
3127 // use it.
3128 //
3129 DefaultData.Cleaned = FALSE;
3130 break;
3131
3132 case EFI_IFR_END_OP:
3133 //
3134 // End Opcode is for Var question.
3135 //
3136 QuestionReferBitField = FALSE;
3137 if (BlockData != NULL) {
3138 if (BlockData->Scope > 0) {
3139 BlockData->Scope--;
3140 }
3141
3142 if (BlockData->Scope == 0) {
3143 BlockData = NULL;
3144 //
3145 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3146 //
3147 SmallestDefaultId = 0xFFFF;
3148 FromOtherDefaultOpcode = FALSE;
3149 }
3150 }
3151
3152 break;
3153
3154 case EFI_IFR_GUID_OP:
3155 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
3156 QuestionReferBitField = TRUE;
3157 }
3158
3159 break;
3160
3161 default:
3162 if (BlockData != NULL) {
3163 if (BlockData->Scope > 0) {
3164 BlockData->Scope = (UINT8)(BlockData->Scope + IfrOpHdr->Scope);
3165 }
3166
3167 if (BlockData->Scope == 0) {
3168 BlockData = NULL;
3169 }
3170 }
3171
3172 break;
3173 }
3174
3175 IfrOffset += IfrOpHdr->Length;
3176 PackageOffset += IfrOpHdr->Length;
3177 }
3178
3179 //
3180 // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3181 // so set the Status to EFI_SUCCESS.
3182 //
3183 if (Status == EFI_NOT_FOUND) {
3184 Status = EFI_SUCCESS;
3185 }
3186
3187Done:
3188 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3189 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3190 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
3191 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3192 LinkDefault = LinkDefault->ForwardLink;
3193 if (DefaultDataPtr->Cleaned == TRUE) {
3194 RemoveEntryList (&DefaultDataPtr->Entry);
3195 FreePool (DefaultDataPtr);
3196 }
3197 }
3198 }
3199
3200 return Status;
3201}
3202
3213 IN EFI_STRING ConfigRequest,
3214 OUT EFI_STRING *Progress
3215 )
3216{
3217 EFI_STRING StringPtr;
3218 IFR_BLOCK_DATA *BlockData;
3219 IFR_BLOCK_DATA *RequestBlockArray;
3220 EFI_STATUS Status;
3221 UINT8 *TmpBuffer;
3222 UINT16 Offset;
3223 UINT16 Width;
3224 LIST_ENTRY *Link;
3225 IFR_BLOCK_DATA *NextBlockData;
3226 UINTN Length;
3227
3228 TmpBuffer = NULL;
3229
3230 //
3231 // Init RequestBlockArray
3232 //
3233 RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3234 if (RequestBlockArray == NULL) {
3235 goto Done;
3236 }
3237
3238 InitializeListHead (&RequestBlockArray->Entry);
3239
3240 //
3241 // Get the request Block array from the request string
3242 // Offset and Width
3243 //
3244
3245 //
3246 // Parse each <RequestElement> if exists
3247 // Only <BlockName> format is supported by this help function.
3248 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3249 //
3250 StringPtr = ConfigRequest;
3251 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", L_STR_LEN (L"&OFFSET=")) == 0) {
3252 //
3253 // Skip the OFFSET string
3254 //
3255 *Progress = StringPtr;
3256 StringPtr += L_STR_LEN (L"&OFFSET=");
3257 //
3258 // Get Offset
3259 //
3260 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3261 if (EFI_ERROR (Status)) {
3262 goto Done;
3263 }
3264
3265 Offset = 0;
3266 CopyMem (
3267 &Offset,
3268 TmpBuffer,
3269 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
3270 );
3271 FreePool (TmpBuffer);
3272
3273 StringPtr += Length;
3274 if (StrnCmp (StringPtr, L"&WIDTH=", L_STR_LEN (L"&WIDTH=")) != 0) {
3275 goto Done;
3276 }
3277
3278 StringPtr += L_STR_LEN (L"&WIDTH=");
3279
3280 //
3281 // Get Width
3282 //
3283 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3284 if (EFI_ERROR (Status)) {
3285 goto Done;
3286 }
3287
3288 Width = 0;
3289 CopyMem (
3290 &Width,
3291 TmpBuffer,
3292 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
3293 );
3294 FreePool (TmpBuffer);
3295
3296 StringPtr += Length;
3297 if ((*StringPtr != 0) && (*StringPtr != L'&')) {
3298 goto Done;
3299 }
3300
3301 //
3302 // Set Block Data
3303 //
3304 BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3305 if (BlockData == NULL) {
3306 goto Done;
3307 }
3308
3309 BlockData->Offset = Offset;
3310 BlockData->Width = Width;
3311 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3312
3313 //
3314 // Skip &VALUE string if &VALUE does exists.
3315 //
3316 if (StrnCmp (StringPtr, L"&VALUE=", L_STR_LEN (L"&VALUE=")) == 0) {
3317 StringPtr += L_STR_LEN (L"&VALUE=");
3318
3319 //
3320 // Get Value
3321 //
3322 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3323 if (EFI_ERROR (Status)) {
3324 goto Done;
3325 }
3326
3327 FreePool (TmpBuffer);
3328 StringPtr += Length;
3329 if ((*StringPtr != 0) && (*StringPtr != L'&')) {
3330 goto Done;
3331 }
3332 }
3333
3334 //
3335 // If '\0', parsing is finished.
3336 //
3337 if (*StringPtr == 0) {
3338 break;
3339 }
3340 }
3341
3342 //
3343 // Merge the requested block data.
3344 //
3345 Link = RequestBlockArray->Entry.ForwardLink;
3346 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
3347 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3348 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
3349 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
3350 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
3351 BlockData->Width = (UINT16)(NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
3352 }
3353
3354 RemoveEntryList (Link->ForwardLink);
3355 FreePool (NextBlockData);
3356 continue;
3357 }
3358
3359 Link = Link->ForwardLink;
3360 }
3361
3362 return RequestBlockArray;
3363
3364Done:
3365 if (RequestBlockArray != NULL) {
3366 //
3367 // Free Link Array RequestBlockArray
3368 //
3369 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3370 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3371 RemoveEntryList (&BlockData->Entry);
3372 FreePool (BlockData);
3373 }
3374
3375 FreePool (RequestBlockArray);
3376 }
3377
3378 return NULL;
3379}
3380
3391 IN EFI_STRING ConfigRequest,
3392 OUT EFI_STRING *Progress
3393 )
3394{
3395 EFI_STRING StringPtr;
3396 EFI_STRING NextTag;
3397 IFR_BLOCK_DATA *BlockData;
3398 IFR_BLOCK_DATA *RequestBlockArray;
3399 BOOLEAN HasValue;
3400
3401 StringPtr = ConfigRequest;
3402
3403 //
3404 // Init RequestBlockArray
3405 //
3406 RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3407 if (RequestBlockArray == NULL) {
3408 goto Done;
3409 }
3410
3411 InitializeListHead (&RequestBlockArray->Entry);
3412
3413 //
3414 // Get the request Block array from the request string
3415 //
3416
3417 //
3418 // Parse each <RequestElement> if exists
3419 // Only <BlockName> format is supported by this help function.
3420 // <BlockName> ::= &'Name***=***
3421 //
3422 while (StringPtr != NULL && *StringPtr == L'&') {
3423 *Progress = StringPtr;
3424 //
3425 // Skip the L"&" string
3426 //
3427 StringPtr += 1;
3428
3429 HasValue = FALSE;
3430 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
3431 *NextTag = L'\0';
3432 HasValue = TRUE;
3433 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
3434 *NextTag = L'\0';
3435 }
3436
3437 //
3438 // Set Block Data
3439 //
3440 BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3441 if (BlockData == NULL) {
3442 goto Done;
3443 }
3444
3445 //
3446 // Get Name
3447 //
3448 BlockData->Name = AllocateCopyPool (StrSize (StringPtr), StringPtr);
3449 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3450
3451 if (HasValue) {
3452 //
3453 // If has value, skip the value.
3454 //
3455 StringPtr = NextTag + 1;
3456 *NextTag = L'=';
3457 StringPtr = StrStr (StringPtr, L"&");
3458 } else if (NextTag != NULL) {
3459 //
3460 // restore the '&' text.
3461 //
3462 StringPtr = NextTag;
3463 *NextTag = L'&';
3464 }
3465 }
3466
3467 return RequestBlockArray;
3468
3469Done:
3470 if (RequestBlockArray != NULL) {
3471 //
3472 // Free Link Array RequestBlockArray
3473 //
3474 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3475 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3476 RemoveEntryList (&BlockData->Entry);
3477 if (BlockData->Name != NULL) {
3478 FreePool (BlockData->Name);
3479 }
3480
3481 FreePool (BlockData);
3482 }
3483
3484 FreePool (RequestBlockArray);
3485 }
3486
3487 return NULL;
3488}
3489
3501BOOLEAN
3503 IN CHAR16 *ConfigHdr,
3504 IN IFR_VARSTORAGE_DATA *VarStorageData,
3505 OUT EFI_STATUS *Status,
3506 IN OUT EFI_STRING *ConfigRequest
3507 )
3508{
3509 BOOLEAN DataExist;
3510 UINTN Length;
3511 LIST_ENTRY *Link;
3512 CHAR16 *FullConfigRequest;
3513 CHAR16 *StringPtr;
3514 IFR_BLOCK_DATA *BlockData;
3515
3516 //
3517 // Append VarStorageData BlockEntry into *Request string
3518 // Now support only one varstore in a form package.
3519 //
3520
3521 //
3522 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3523 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3524 //
3525
3526 //
3527 // Compute the length of the entire request starting with <ConfigHdr> and a
3528 // Null-terminator
3529 //
3530 DataExist = FALSE;
3531 Length = StrLen (ConfigHdr) + 1;
3532
3533 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3534 DataExist = TRUE;
3535 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3536 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3537 //
3538 // Add <BlockName> length for each Name
3539 //
3540 // <BlockName> ::= &Name1&Name2&...
3541 // |1| StrLen(Name1)
3542 //
3543 Length = Length + (1 + StrLen (BlockData->Name));
3544 } else {
3545 //
3546 // Add <BlockName> length for each Offset/Width pair
3547 //
3548 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3549 // | 8 | 4 | 7 | 4 |
3550 //
3551 Length = Length + (8 + 4 + 7 + 4);
3552 }
3553 }
3554
3555 //
3556 // No any request block data is found. The request string can't be constructed.
3557 //
3558 if (!DataExist) {
3559 *Status = EFI_SUCCESS;
3560 return FALSE;
3561 }
3562
3563 //
3564 // Allocate buffer for the entire <ConfigRequest>
3565 //
3566 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
3567 if (FullConfigRequest == NULL) {
3568 *Status = EFI_OUT_OF_RESOURCES;
3569 return FALSE;
3570 }
3571
3572 StringPtr = FullConfigRequest;
3573
3574 //
3575 // Start with <ConfigHdr>
3576 //
3577 StrCpyS (StringPtr, Length, ConfigHdr);
3578 StringPtr += StrLen (StringPtr);
3579
3580 //
3581 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3582 //
3583 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3584 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3585 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3586 //
3587 // Append &Name1\0
3588 //
3589 UnicodeSPrint (
3590 StringPtr,
3591 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
3592 L"&%s",
3593 BlockData->Name
3594 );
3595 } else {
3596 //
3597 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3598 //
3599 UnicodeSPrint (
3600 StringPtr,
3601 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
3602 L"&OFFSET=%04X&WIDTH=%04X",
3603 BlockData->Offset,
3604 BlockData->Width
3605 );
3606 }
3607
3608 StringPtr += StrLen (StringPtr);
3609 }
3610
3611 //
3612 // Set to the got full request string.
3613 //
3614 HiiToLower (FullConfigRequest);
3615
3616 if (*ConfigRequest != NULL) {
3617 FreePool (*ConfigRequest);
3618 }
3619
3620 *ConfigRequest = FullConfigRequest;
3621
3622 return TRUE;
3623}
3624
3635EFI_STATUS
3637 IN IFR_VARSTORAGE_DATA *VarStorageData,
3638 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3639 OUT EFI_STRING *ConfigHdr
3640 )
3641{
3642 EFI_STRING GuidStr;
3643 EFI_STRING NameStr;
3644 EFI_STRING PathStr;
3645 UINTN Length;
3646 EFI_STATUS Status;
3647
3648 Status = EFI_SUCCESS;
3649 NameStr = NULL;
3650 GuidStr = NULL;
3651 PathStr = NULL;
3652
3653 //
3654 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3655 //
3656 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&VarStorageData->Guid, 1, &GuidStr);
3657 if (VarStorageData->Name != NULL) {
3658 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *)VarStorageData->Name, 2, &NameStr);
3659 } else {
3660 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3661 }
3662
3664 L"PATH=",
3665 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
3666 (VOID *)DevicePath,
3667 1,
3668 &PathStr
3669 );
3670 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
3671 if (VarStorageData->Name == NULL) {
3672 Length += 1;
3673 }
3674
3675 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
3676 if (*ConfigHdr == NULL) {
3677 Status = EFI_OUT_OF_RESOURCES;
3678 goto Done;
3679 }
3680
3681 StrCpyS (*ConfigHdr, Length, GuidStr);
3682 StrCatS (*ConfigHdr, Length, NameStr);
3683 if (VarStorageData->Name == NULL) {
3684 StrCatS (*ConfigHdr, Length, L"&");
3685 }
3686
3687 StrCatS (*ConfigHdr, Length, PathStr);
3688
3689 //
3690 // Remove the last character L'&'
3691 //
3692 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
3693
3694Done:
3695 if (GuidStr != NULL) {
3696 FreePool (GuidStr);
3697 }
3698
3699 if (NameStr != NULL) {
3700 FreePool (NameStr);
3701 }
3702
3703 if (PathStr != NULL) {
3704 FreePool (PathStr);
3705 }
3706
3707 return Status;
3708}
3709
3734VOID
3736 IN LIST_ENTRY *BlockLink
3737 )
3738{
3739 LIST_ENTRY *Link;
3740 LIST_ENTRY *ListEntry;
3741 LIST_ENTRY *LinkDefault;
3742 IFR_BLOCK_DATA *BlockData;
3743 IFR_DEFAULT_DATA *DefaultValueData;
3744 UINTN StartBit;
3745 UINTN EndBit;
3746 UINT32 BitFieldDefaultValue;
3747
3748 for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
3749 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3750 if (!BlockData->IsBitVar) {
3751 continue;
3752 }
3753
3754 ListEntry = &BlockData->DefaultValueEntry;
3755 //
3756 // Update the default value in the block data with all existing default id.
3757 //
3758 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3759 //
3760 // Get the default data, and the value of the default data is for some field in the block.
3761 // Note: Default value for bit field question is stored as UINT32.
3762 //
3763 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3764 BitFieldDefaultValue = DefaultValueData->Value.u32;
3765
3766 StartBit = BlockData->BitOffset % 8;
3767 EndBit = StartBit + BlockData->BitWidth - 1;
3768
3769 //
3770 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3771 //
3772 DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);
3773 }
3774 }
3775}
3776
3814VOID
3816 IN OUT IFR_BLOCK_DATA *FirstBlock,
3817 IN OUT IFR_BLOCK_DATA *SecondBlock
3818 )
3819{
3820 LIST_ENTRY *FirstListEntry;
3821 LIST_ENTRY *SecondListEntry;
3822 LIST_ENTRY *FirstDefaultLink;
3823 LIST_ENTRY *SecondDefaultLink;
3824 IFR_DEFAULT_DATA *FirstDefaultValueData;
3825 IFR_DEFAULT_DATA *SecondDefaultValueData;
3826 UINT32 *FirstDefaultValue;
3827 UINT32 *SecondDefaultValue;
3828 UINT64 TotalValue;
3829 UINT64 ShiftedValue;
3830 UINT16 OffsetShift;
3831
3832 FirstListEntry = &FirstBlock->DefaultValueEntry;
3833 for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {
3834 FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);
3835 SecondListEntry = &SecondBlock->DefaultValueEntry;
3836 for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {
3837 SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);
3838 if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {
3839 continue;
3840 }
3841
3842 //
3843 // Find default value with same default id in the two blocks.
3844 // Note: Default value for bit field question is stored as UINT32 type.
3845 //
3846 FirstDefaultValue = &FirstDefaultValueData->Value.u32;
3847 SecondDefaultValue = &SecondDefaultValueData->Value.u32;
3848 //
3849 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3850 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3851 // on the offset and width of FirstBlock and SecondBlock.
3852 //
3853 if (FirstBlock->Offset > SecondBlock->Offset) {
3854 OffsetShift = FirstBlock->Offset - SecondBlock->Offset;
3855 ShiftedValue = LShiftU64 ((UINT64)(*FirstDefaultValue), OffsetShift * 8);
3856 TotalValue = ShiftedValue | (UINT64)(*SecondDefaultValue);
3857 *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);
3858 *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);
3859 } else {
3860 OffsetShift = SecondBlock->Offset -FirstBlock->Offset;
3861 ShiftedValue = LShiftU64 ((UINT64)(*SecondDefaultValue), OffsetShift * 8);
3862 TotalValue = ShiftedValue | (UINT64)(*FirstDefaultValue);
3863 *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);
3864 *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);
3865 }
3866 }
3867 }
3868}
3869
3877VOID
3879 IN LIST_ENTRY *BlockLink
3880 )
3881{
3882 LIST_ENTRY *Link;
3883 LIST_ENTRY *TempLink;
3884 IFR_BLOCK_DATA *BlockData;
3885 IFR_BLOCK_DATA *NextBlockData;
3886
3887 //
3888 // 1. Update default value in BitVar block data.
3889 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3890 // is for related bit field in the block. so we need to set the default value to the related bit
3891 // fields in the block data if the block data is used as bit varstore, then the default value of
3892 // the block will be updated.
3893 //
3894 UpdateDefaultValue (BlockLink);
3895
3896 //
3897 // 2.Update default value for overlap BitVar blcok datas.
3898 // For block datas have overlap region, we need to merge the default value in different blocks.
3899 //
3900 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
3901 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3902 if (!BlockData->IsBitVar) {
3903 continue;
3904 }
3905
3906 for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {
3907 NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);
3908 if (!NextBlockData->IsBitVar || (NextBlockData->Offset >= BlockData->Offset + BlockData->Width) || (BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width)) {
3909 continue;
3910 }
3911
3912 //
3913 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3914 //
3915 MergeBlockDefaultValue (BlockData, NextBlockData);
3916 }
3917 }
3918}
3919
3932EFI_STATUS
3934 IN EFI_HII_HANDLE HiiHandle,
3935 IN CHAR16 *ConfigHdr,
3936 IN IFR_VARSTORAGE_DATA *VarStorageData,
3937 IN IFR_DEFAULT_DATA *DefaultIdArray,
3938 IN OUT EFI_STRING *DefaultAltCfgResp
3939 )
3940{
3941 BOOLEAN DataExist;
3942 UINTN Length;
3943 LIST_ENTRY *Link;
3944 LIST_ENTRY *LinkData;
3945 LIST_ENTRY *LinkDefault;
3946 LIST_ENTRY *ListEntry;
3947 CHAR16 *StringPtr;
3948 IFR_BLOCK_DATA *BlockData;
3949 IFR_DEFAULT_DATA *DefaultId;
3950 IFR_DEFAULT_DATA *DefaultValueData;
3951 UINTN Width;
3952 UINT8 *TmpBuffer;
3953 CHAR16 *DefaultString;
3954 UINTN StrSize;
3955
3956 BlockData = NULL;
3957 DataExist = FALSE;
3958 DefaultString = NULL;
3959 //
3960 // Add length for <ConfigHdr> + '\0'
3961 //
3962 Length = StrLen (ConfigHdr) + 1;
3963
3964 UpdateBlockDataArray (&VarStorageData->BlockEntry);
3965
3966 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3967 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3968 //
3969 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3970 // |1| StrLen (ConfigHdr) | 8 | 4 |
3971 //
3972 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
3973
3974 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3975 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3976 ListEntry = &BlockData->DefaultValueEntry;
3977 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3978 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3979 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3980 continue;
3981 }
3982
3983 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3984 //
3985 // Add length for "&Name1=zzzzzzzzzzzz"
3986 // |1|Name|1|Value|
3987 //
3988 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
3989 } else {
3990 //
3991 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3992 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3993 //
3994 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
3995 }
3996
3997 DataExist = TRUE;
3998 }
3999 }
4000 }
4001
4002 //
4003 // No default value is found. The default string doesn't exist.
4004 //
4005 if (!DataExist) {
4006 return EFI_SUCCESS;
4007 }
4008
4009 //
4010 // Allocate buffer for the entire <DefaultAltCfgResp>
4011 //
4012 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
4013 if (*DefaultAltCfgResp == NULL) {
4014 return EFI_OUT_OF_RESOURCES;
4015 }
4016
4017 StringPtr = *DefaultAltCfgResp;
4018
4019 //
4020 // Start with <ConfigHdr>
4021 //
4022 StrCpyS (StringPtr, Length, ConfigHdr);
4023 StringPtr += StrLen (StringPtr);
4024
4025 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
4026 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
4027 //
4028 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
4029 // |1| StrLen (ConfigHdr) | 8 | 4 |
4030 //
4031 UnicodeSPrint (
4032 StringPtr,
4033 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
4034 L"&%s&ALTCFG=%04X",
4035 ConfigHdr,
4036 DefaultId->DefaultId
4037 );
4038 StringPtr += StrLen (StringPtr);
4039
4040 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
4041 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
4042 ListEntry = &BlockData->DefaultValueEntry;
4043 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
4044 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
4045 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
4046 continue;
4047 }
4048
4049 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
4050 UnicodeSPrint (
4051 StringPtr,
4052 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
4053 L"&%s=",
4054 BlockData->Name
4055 );
4056 StringPtr += StrLen (StringPtr);
4057 } else {
4058 //
4059 // Add <BlockConfig>
4060 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
4061 //
4062 UnicodeSPrint (
4063 StringPtr,
4064 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
4065 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
4066 BlockData->Offset,
4067 BlockData->Width
4068 );
4069 StringPtr += StrLen (StringPtr);
4070 }
4071
4072 Width = BlockData->Width;
4073 //
4074 // Convert Value to a hex string in "%x" format
4075 // NOTE: This is in the opposite byte that GUID and PATH use
4076 //
4077 if (BlockData->OpCode == EFI_IFR_STRING_OP) {
4078 DefaultString = InternalGetString (HiiHandle, DefaultValueData->Value.string);
4079 TmpBuffer = AllocateZeroPool (Width);
4080 ASSERT (TmpBuffer != NULL);
4081 if (DefaultString != NULL) {
4082 StrSize = StrLen (DefaultString)* sizeof (CHAR16);
4083 if (StrSize > Width) {
4084 StrSize = Width;
4085 }
4086
4087 CopyMem (TmpBuffer, (UINT8 *)DefaultString, StrSize);
4088 }
4089 } else {
4090 TmpBuffer = (UINT8 *)&(DefaultValueData->Value);
4091 }
4092
4093 for ( ; Width > 0 && (TmpBuffer != NULL); Width--) {
4094 UnicodeValueToStringS (
4095 StringPtr,
4096 Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),
4097 PREFIX_ZERO | RADIX_HEX,
4098 TmpBuffer[Width - 1],
4099 2
4100 );
4101 StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));
4102 }
4103
4104 if (DefaultString != NULL) {
4105 FreePool (DefaultString);
4106 DefaultString = NULL;
4107 }
4108
4109 if ((BlockData->OpCode == EFI_IFR_STRING_OP) && (TmpBuffer != NULL)) {
4110 FreePool (TmpBuffer);
4111 TmpBuffer = NULL;
4112 }
4113 }
4114 }
4115 }
4116
4117 HiiToLower (*DefaultAltCfgResp);
4118
4119 return EFI_SUCCESS;
4120}
4121
4165EFI_STATUS
4166EFIAPI
4168 IN HII_DATABASE_RECORD *DataBaseRecord,
4169 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
4170 IN OUT EFI_STRING *Request,
4171 IN OUT EFI_STRING *AltCfgResp,
4172 OUT EFI_STRING *PointerProgress OPTIONAL
4173 )
4174{
4175 EFI_STATUS Status;
4176 UINT8 *HiiFormPackage;
4177 UINTN PackageSize;
4178 IFR_BLOCK_DATA *RequestBlockArray;
4179 IFR_BLOCK_DATA *BlockData;
4180 IFR_DEFAULT_DATA *DefaultValueData;
4181 IFR_DEFAULT_DATA *DefaultId;
4182 IFR_DEFAULT_DATA *DefaultIdArray;
4183 IFR_VARSTORAGE_DATA *VarStorageData;
4184 EFI_STRING DefaultAltCfgResp;
4185 EFI_STRING ConfigHdr;
4186 EFI_STRING StringPtr;
4187 EFI_STRING Progress;
4188
4189 if ((DataBaseRecord == NULL) || (DevicePath == NULL) || (Request == NULL) || (AltCfgResp == NULL)) {
4190 return EFI_INVALID_PARAMETER;
4191 }
4192
4193 //
4194 // Initialize the local variables.
4195 //
4196 RequestBlockArray = NULL;
4197 DefaultIdArray = NULL;
4198 VarStorageData = NULL;
4199 DefaultAltCfgResp = NULL;
4200 ConfigHdr = NULL;
4201 HiiFormPackage = NULL;
4202 PackageSize = 0;
4203 Progress = *Request;
4204
4205 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
4206 if (EFI_ERROR (Status)) {
4207 goto Done;
4208 }
4209
4210 //
4211 // 1. Get the request block array by Request String when Request string contains the block array.
4212 //
4213 StringPtr = NULL;
4214 if (*Request != NULL) {
4215 StringPtr = *Request;
4216 //
4217 // Jump <ConfigHdr>
4218 //
4219 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
4220 Status = EFI_INVALID_PARAMETER;
4221 goto Done;
4222 }
4223
4224 StringPtr += L_STR_LEN (L"GUID=");
4225 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", L_STR_LEN (L"&NAME=")) != 0) {
4226 StringPtr++;
4227 }
4228
4229 if (*StringPtr == L'\0') {
4230 Status = EFI_INVALID_PARAMETER;
4231 goto Done;
4232 }
4233
4234 StringPtr += L_STR_LEN (L"&NAME=");
4235 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", L_STR_LEN (L"&PATH=")) != 0) {
4236 StringPtr++;
4237 }
4238
4239 if (*StringPtr == L'\0') {
4240 Status = EFI_INVALID_PARAMETER;
4241 goto Done;
4242 }
4243
4244 StringPtr += L_STR_LEN (L"&PATH=");
4245 while (*StringPtr != L'\0' && *StringPtr != L'&') {
4246 StringPtr++;
4247 }
4248
4249 if (*StringPtr == L'\0') {
4250 //
4251 // No request block is found.
4252 //
4253 StringPtr = NULL;
4254 }
4255 }
4256
4257 //
4258 // If StringPtr != NULL, get the request elements.
4259 //
4260 if (StringPtr != NULL) {
4261 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
4262 RequestBlockArray = GetBlockElement (StringPtr, &Progress);
4263 } else {
4264 RequestBlockArray = GetNameElement (StringPtr, &Progress);
4265 }
4266
4267 if (RequestBlockArray == NULL) {
4268 Status = EFI_INVALID_PARAMETER;
4269 goto Done;
4270 }
4271 }
4272
4273 //
4274 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4275 //
4276 DefaultIdArray = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
4277 if (DefaultIdArray == NULL) {
4278 Status = EFI_OUT_OF_RESOURCES;
4279 goto Done;
4280 }
4281
4282 InitializeListHead (&DefaultIdArray->Entry);
4283
4284 //
4285 // Initialize VarStorageData to store the var store Block and Default value information.
4286 //
4287 VarStorageData = (IFR_VARSTORAGE_DATA *)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
4288 if (VarStorageData == NULL) {
4289 Status = EFI_OUT_OF_RESOURCES;
4290 goto Done;
4291 }
4292
4293 InitializeListHead (&VarStorageData->Entry);
4294 InitializeListHead (&VarStorageData->BlockEntry);
4295
4296 //
4297 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4298 //
4299
4300 //
4301 // Parse the opcode in form package to get the default setting.
4302 //
4303 Status = ParseIfrData (
4304 DataBaseRecord->Handle,
4305 HiiFormPackage,
4306 (UINT32)PackageSize,
4307 *Request,
4308 RequestBlockArray,
4309 VarStorageData,
4310 DefaultIdArray
4311 );
4312 if (EFI_ERROR (Status)) {
4313 goto Done;
4314 }
4315
4316 //
4317 // No requested varstore in IFR data and directly return
4318 //
4319 if ((VarStorageData->Type == 0) && (VarStorageData->Name == NULL)) {
4320 Status = EFI_SUCCESS;
4321 goto Done;
4322 }
4323
4324 //
4325 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4326 //
4327 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
4328 if (EFI_ERROR (Status)) {
4329 goto Done;
4330 }
4331
4332 if (RequestBlockArray == NULL) {
4333 if (!GenerateConfigRequest (ConfigHdr, VarStorageData, &Status, Request)) {
4334 goto Done;
4335 }
4336 }
4337
4338 //
4339 // 4. Construct Default Value string in AltResp according to request element.
4340 // Go through all VarStorageData Entry and get the DefaultId array for each one
4341 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4342 //
4343 Status = GenerateAltConfigResp (DataBaseRecord->Handle, ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
4344 if (EFI_ERROR (Status)) {
4345 goto Done;
4346 }
4347
4348 //
4349 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4350 //
4351 if ((*AltCfgResp != NULL) && (DefaultAltCfgResp != NULL)) {
4352 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
4353 FreePool (DefaultAltCfgResp);
4354 } else if (*AltCfgResp == NULL) {
4355 *AltCfgResp = DefaultAltCfgResp;
4356 }
4357
4358Done:
4359 if (RequestBlockArray != NULL) {
4360 //
4361 // Free Link Array RequestBlockArray
4362 //
4363 while (!IsListEmpty (&RequestBlockArray->Entry)) {
4364 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
4365 RemoveEntryList (&BlockData->Entry);
4366 if (BlockData->Name != NULL) {
4367 FreePool (BlockData->Name);
4368 }
4369
4370 FreePool (BlockData);
4371 }
4372
4373 FreePool (RequestBlockArray);
4374 }
4375
4376 if (VarStorageData != NULL) {
4377 //
4378 // Free link array VarStorageData
4379 //
4380 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
4381 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
4382 RemoveEntryList (&BlockData->Entry);
4383 if (BlockData->Name != NULL) {
4384 FreePool (BlockData->Name);
4385 }
4386
4387 //
4388 // Free default value link array
4389 //
4390 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
4391 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
4392 RemoveEntryList (&DefaultValueData->Entry);
4393 FreePool (DefaultValueData);
4394 }
4395
4396 FreePool (BlockData);
4397 }
4398
4399 if (VarStorageData->Name != NULL) {
4400 FreePool (VarStorageData->Name);
4401 VarStorageData->Name = NULL;
4402 }
4403
4404 FreePool (VarStorageData);
4405 }
4406
4407 if (DefaultIdArray != NULL) {
4408 //
4409 // Free DefaultId Array
4410 //
4411 while (!IsListEmpty (&DefaultIdArray->Entry)) {
4412 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
4413 RemoveEntryList (&DefaultId->Entry);
4414 FreePool (DefaultId);
4415 }
4416
4417 FreePool (DefaultIdArray);
4418 }
4419
4420 //
4421 // Free the allocated string
4422 //
4423 if (ConfigHdr != NULL) {
4424 FreePool (ConfigHdr);
4425 }
4426
4427 //
4428 // Free Package data
4429 //
4430 if (HiiFormPackage != NULL) {
4431 FreePool (HiiFormPackage);
4432 }
4433
4434 if (PointerProgress != NULL) {
4435 if (*Request == NULL) {
4436 *PointerProgress = NULL;
4437 } else if (EFI_ERROR (Status)) {
4438 *PointerProgress = *Request;
4439 } else {
4440 *PointerProgress = *Request + StrLen (*Request);
4441 }
4442 }
4443
4444 return Status;
4445}
4446
4473EFI_STATUS
4475 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4476 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4477 IN EFI_STRING Request,
4478 OUT EFI_STRING *RequestResp,
4479 OUT EFI_STRING *AccessProgress
4480 )
4481{
4482 EFI_STATUS Status;
4483 EFI_STRING VarStoreName;
4484 UINTN NameSize;
4485 UINT8 *VarStore;
4486 UINTN BufferSize;
4487
4488 Status = EFI_SUCCESS;
4489 BufferSize = 0;
4490 VarStore = NULL;
4491 VarStoreName = NULL;
4492 *AccessProgress = Request;
4493
4494 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
4495 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
4496 if (VarStoreName == NULL) {
4497 Status = EFI_OUT_OF_RESOURCES;
4498 goto Done;
4499 }
4500
4501 AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
4502
4503 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4504 if (Status != EFI_BUFFER_TOO_SMALL) {
4505 goto Done;
4506 }
4507
4508 VarStore = AllocateZeroPool (BufferSize);
4509 ASSERT (VarStore != NULL);
4510 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4511 if (EFI_ERROR (Status)) {
4512 goto Done;
4513 }
4514
4515 Status = HiiBlockToConfig (This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
4516 if (EFI_ERROR (Status)) {
4517 goto Done;
4518 }
4519
4520Done:
4521 if (VarStoreName != NULL) {
4522 FreePool (VarStoreName);
4523 }
4524
4525 if (VarStore != NULL) {
4526 FreePool (VarStore);
4527 }
4528
4529 return Status;
4530}
4531
4550EFI_STATUS
4552 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4553 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4554 IN EFI_STRING RequestResp,
4555 OUT EFI_STRING *Result
4556 )
4557{
4558 EFI_STATUS Status;
4559 EFI_STRING VarStoreName;
4560 UINTN NameSize;
4561 UINT8 *VarStore;
4562 UINTN BufferSize;
4563 UINTN BlockSize;
4564
4565 Status = EFI_SUCCESS;
4566 BufferSize = 0;
4567 VarStore = NULL;
4568 VarStoreName = NULL;
4569 *Result = RequestResp;
4570
4571 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
4572 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
4573 if (VarStoreName == NULL) {
4574 Status = EFI_OUT_OF_RESOURCES;
4575 goto Done;
4576 }
4577
4578 AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
4579
4580 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4581 if (Status != EFI_BUFFER_TOO_SMALL) {
4582 DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
4583 goto Done;
4584 }
4585
4586 BlockSize = BufferSize;
4587 VarStore = AllocateZeroPool (BufferSize);
4588 ASSERT (VarStore != NULL);
4589 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4590 if (EFI_ERROR (Status)) {
4591 goto Done;
4592 }
4593
4594 Status = HiiConfigToBlock (This, RequestResp, VarStore, &BlockSize, Result);
4595 if (EFI_ERROR (Status)) {
4596 goto Done;
4597 }
4598
4599 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
4600 if (EFI_ERROR (Status)) {
4601 *Result = RequestResp;
4602 goto Done;
4603 }
4604
4605Done:
4606 if (VarStoreName != NULL) {
4607 FreePool (VarStoreName);
4608 }
4609
4610 if (VarStore != NULL) {
4611 FreePool (VarStore);
4612 }
4613
4614 return Status;
4615}
4616
4626CHAR16 *
4628 CHAR16 *ConfigElements
4629 )
4630{
4631 CHAR16 *StringPtr;
4632 CHAR16 *RetVal;
4633
4634 StringPtr = ConfigElements;
4635
4636 while (1) {
4637 RetVal = StringPtr;
4638 if (StrnCmp (StringPtr, L"&OFFSET=", L_STR_LEN (L"&OFFSET=")) != 0) {
4639 return RetVal;
4640 }
4641
4642 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", L_STR_LEN (L"&WIDTH=")) != 0) {
4643 StringPtr++;
4644 }
4645
4646 if (*StringPtr == L'\0') {
4647 return RetVal;
4648 }
4649
4650 StringPtr += L_STR_LEN (L"&WIDTH=");
4651 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", L_STR_LEN (L"&OFFSET=")) != 0) {
4652 StringPtr++;
4653 }
4654
4655 if (*StringPtr == L'\0') {
4656 return NULL;
4657 }
4658 }
4659}
4660
4671CHAR16 *
4673 CHAR16 *ConfigElements
4674 )
4675{
4676 CHAR16 *StringPtr;
4677 CHAR16 *RetVal;
4678
4679 StringPtr = ConfigElements;
4680
4681 while (1) {
4682 RetVal = StringPtr;
4683 if (*StringPtr != L'&') {
4684 return RetVal;
4685 }
4686
4687 StringPtr += 1;
4688
4689 StringPtr = StrStr (StringPtr, L"&");
4690
4691 if (StringPtr == NULL) {
4692 return NULL;
4693 }
4694 }
4695}
4696
4706CHAR16 *
4708 CHAR16 *ConfigRequest
4709 )
4710{
4711 BOOLEAN HasNameField;
4712 CHAR16 *StringPtr;
4713
4714 HasNameField = TRUE;
4715 StringPtr = ConfigRequest;
4716
4717 //
4718 // Check <ConfigHdr>
4719 //
4720 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
4721 return ConfigRequest;
4722 }
4723
4724 StringPtr += L_STR_LEN (L"GUID=");
4725 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", L_STR_LEN (L"&NAME=")) != 0) {
4726 StringPtr++;
4727 }
4728
4729 if (*StringPtr == L'\0') {
4730 return ConfigRequest;
4731 }
4732
4733 StringPtr += L_STR_LEN (L"&NAME=");
4734 if (*StringPtr == L'&') {
4735 HasNameField = FALSE;
4736 }
4737
4738 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", L_STR_LEN (L"&PATH=")) != 0) {
4739 StringPtr++;
4740 }
4741
4742 if (*StringPtr == L'\0') {
4743 return ConfigRequest;
4744 }
4745
4746 StringPtr += L_STR_LEN (L"&PATH=");
4747 while (*StringPtr != L'\0' && *StringPtr != L'&') {
4748 StringPtr++;
4749 }
4750
4751 if (*StringPtr == L'\0') {
4752 return NULL;
4753 }
4754
4755 if (HasNameField) {
4756 //
4757 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4758 //
4759 return OffsetWidthValidate (StringPtr);
4760 } else {
4761 //
4762 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4763 //
4764 return NameValueValidate (StringPtr);
4765 }
4766}
4767
4809EFI_STATUS
4810EFIAPI
4812 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4813 IN CONST EFI_STRING Request,
4814 OUT EFI_STRING *Progress,
4815 OUT EFI_STRING *Results
4816 )
4817{
4819 EFI_STRING StringPtr;
4820 EFI_STRING ConfigRequest;
4821 UINTN Length;
4822 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4823 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4824 EFI_STATUS Status;
4825 LIST_ENTRY *Link;
4826 HII_DATABASE_RECORD *Database;
4827 UINT8 *DevicePathPkg;
4828 UINT8 *CurrentDevicePath;
4829 EFI_HANDLE DriverHandle;
4830 EFI_HII_HANDLE HiiHandle;
4831 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4832 EFI_STRING AccessProgress;
4833 EFI_STRING AccessResults;
4834 EFI_STRING AccessProgressBackup;
4835 EFI_STRING AccessResultsBackup;
4836 EFI_STRING DefaultResults;
4837 BOOLEAN FirstElement;
4838 BOOLEAN IfrDataParsedFlag;
4839 BOOLEAN IsEfiVarStore;
4840 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4841 EFI_STRING ErrorPtr;
4842 UINTN DevicePathSize;
4843 UINTN ConigStringSize;
4844 UINTN ConigStringSizeNewsize;
4845 EFI_STRING ConfigStringPtr;
4846
4847 if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {
4848 return EFI_INVALID_PARAMETER;
4849 }
4850
4851 if (Request == NULL) {
4852 *Progress = NULL;
4853 return EFI_INVALID_PARAMETER;
4854 }
4855
4857 StringPtr = Request;
4858 *Progress = StringPtr;
4859 DefaultResults = NULL;
4860 ConfigRequest = NULL;
4861 Status = EFI_SUCCESS;
4862 AccessResults = NULL;
4863 AccessProgress = NULL;
4864 AccessResultsBackup = NULL;
4865 AccessProgressBackup = NULL;
4866 DevicePath = NULL;
4867 IfrDataParsedFlag = FALSE;
4868 IsEfiVarStore = FALSE;
4869 EfiVarStoreInfo = NULL;
4870
4871 //
4872 // The first element of <MultiConfigRequest> should be
4873 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4874 //
4875 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
4876 return EFI_INVALID_PARAMETER;
4877 }
4878
4879 FirstElement = TRUE;
4880
4881 //
4882 // Allocate a fix length of memory to store Results. Reallocate memory for
4883 // Results if this fix length is insufficient.
4884 //
4885 *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
4886 if (*Results == NULL) {
4887 return EFI_OUT_OF_RESOURCES;
4888 }
4889
4890 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) == 0) {
4891 //
4892 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4893 // or most recent & before the error.
4894 //
4895 if (StringPtr == Request) {
4896 *Progress = StringPtr;
4897 } else {
4898 *Progress = StringPtr - 1;
4899 }
4900
4901 //
4902 // Process each <ConfigRequest> of <MultiConfigRequest>
4903 //
4904 Length = CalculateConfigStringLen (StringPtr);
4905 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4906 if (ConfigRequest == NULL) {
4907 Status = EFI_OUT_OF_RESOURCES;
4908 goto Done;
4909 }
4910
4911 *(ConfigRequest + Length) = 0;
4912
4913 //
4914 // Get the UEFI device path
4915 //
4916 Status = GetDevicePath (ConfigRequest, (UINT8 **)&DevicePath);
4917 if (EFI_ERROR (Status)) {
4918 goto Done;
4919 }
4920
4921 //
4922 // Find driver which matches the routing data.
4923 //
4924 DriverHandle = NULL;
4925 HiiHandle = NULL;
4926 Database = NULL;
4927 for (Link = Private->DatabaseList.ForwardLink;
4928 Link != &Private->DatabaseList;
4929 Link = Link->ForwardLink
4930 )
4931 {
4932 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4933 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4934 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4935 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
4936 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigRequest)) {
4937 DriverHandle = Database->DriverHandle;
4938 HiiHandle = Database->Handle;
4939 break;
4940 }
4941 }
4942 }
4943
4944 //
4945 // Try to find driver handle by device path.
4946 //
4947 if (DriverHandle == NULL) {
4948 TempDevicePath = DevicePath;
4949 Status = gBS->LocateDevicePath (
4951 &TempDevicePath,
4952 &DriverHandle
4953 );
4954 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4955 //
4956 // Routing data does not match any known driver.
4957 // Set Progress to the 'G' in "GUID" of the routing header.
4958 //
4959 *Progress = StringPtr;
4960 Status = EFI_NOT_FOUND;
4961 goto Done;
4962 }
4963 }
4964
4965 //
4966 // Validate ConfigRequest String.
4967 //
4968 ErrorPtr = ConfigRequestValidate (ConfigRequest);
4969 if (ErrorPtr != NULL) {
4970 *Progress = StrStr (StringPtr, ErrorPtr);
4971 Status = EFI_INVALID_PARAMETER;
4972 goto Done;
4973 }
4974
4975 //
4976 // Check whether ConfigRequest contains request string.
4977 //
4978 IfrDataParsedFlag = FALSE;
4979 if ((HiiHandle != NULL) && !InternalGetElementsFromRequest (ConfigRequest)) {
4980 //
4981 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4982 //
4983 IfrDataParsedFlag = TRUE;
4984 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
4985 if (EFI_ERROR (Status)) {
4986 //
4987 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4988 // Map it to the progress on <MultiConfigRequest> then return it.
4989 //
4990 ASSERT (AccessProgress != NULL);
4991 *Progress = StrStr (StringPtr, AccessProgress);
4992 goto Done;
4993 }
4994
4995 //
4996 // Not any request block is found.
4997 //
4998 if (!InternalGetElementsFromRequest (ConfigRequest)) {
4999 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
5000 goto NextConfigString;
5001 }
5002 }
5003
5004 //
5005 // Check whether this ConfigRequest is search from Efi varstore type storage.
5006 //
5007 Status = GetVarStoreType (Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
5008 if (EFI_ERROR (Status)) {
5009 goto Done;
5010 }
5011
5012 if (IsEfiVarStore) {
5013 //
5014 // Call the GetVariable function to extract settings.
5015 //
5016 Status = GetConfigRespFromEfiVarStore (This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
5017 FreePool (EfiVarStoreInfo);
5018 if (EFI_ERROR (Status)) {
5019 //
5020 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5021 // Map it to the progress on <MultiConfigRequest> then return it.
5022 //
5023 *Progress = StrStr (StringPtr, AccessProgress);
5024 goto Done;
5025 }
5026
5027 //
5028 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
5029 //
5030 Status = gBS->HandleProtocol (
5031 DriverHandle,
5032 &gEfiHiiConfigAccessProtocolGuid,
5033 (VOID **)&ConfigAccess
5034 );
5035 if (EFI_ERROR (Status)) {
5036 //
5037 // The driver has EfiVarStore, may not install ConfigAccess protocol.
5038 // So ignore the error status in this case.
5039 //
5040 Status = EFI_SUCCESS;
5041 } else {
5042 Status = ConfigAccess->ExtractConfig (
5043 ConfigAccess,
5044 ConfigRequest,
5045 &AccessProgressBackup,
5046 &AccessResultsBackup
5047 );
5048 if (!EFI_ERROR (Status)) {
5049 //
5050 // Merge the AltCfgResp in AccessResultsBackup to AccessResults
5051 //
5052 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
5053 ConigStringSize = StrSize (AccessResults);
5054 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
5055 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
5056 AccessResults = (EFI_STRING)ReallocatePool (
5057 ConigStringSize,
5058 ConigStringSizeNewsize,
5059 AccessResults
5060 );
5061 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
5062 }
5063 } else {
5064 //
5065 // In the ExtractConfig function of some driver may not support EfiVarStore,
5066 // may return error status, just ignore the error status in this case.
5067 //
5068 Status = EFI_SUCCESS;
5069 }
5070
5071 if (AccessResultsBackup != NULL) {
5072 FreePool (AccessResultsBackup);
5073 AccessResultsBackup = NULL;
5074 }
5075 }
5076 } else {
5077 //
5078 // Call corresponding ConfigAccess protocol to extract settings
5079 //
5080 Status = gBS->HandleProtocol (
5081 DriverHandle,
5082 &gEfiHiiConfigAccessProtocolGuid,
5083 (VOID **)&ConfigAccess
5084 );
5085 if (EFI_ERROR (Status)) {
5086 goto Done;
5087 }
5088
5089 Status = ConfigAccess->ExtractConfig (
5090 ConfigAccess,
5091 ConfigRequest,
5092 &AccessProgress,
5093 &AccessResults
5094 );
5095 }
5096
5097 if (EFI_ERROR (Status)) {
5098 //
5099 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5100 // Map it to the progress on <MultiConfigRequest> then return it.
5101 //
5102 *Progress = StrStr (StringPtr, AccessProgress);
5103 goto Done;
5104 }
5105
5106 //
5107 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5108 // which separates the first <ConfigAltResp> and the following ones.
5109 //
5110 ASSERT (*AccessProgress == 0);
5111
5112 //
5113 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5114 //
5115 if (!IfrDataParsedFlag && (HiiHandle != NULL)) {
5116 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
5117 ASSERT_EFI_ERROR (Status);
5118 }
5119
5120 FreePool (DevicePath);
5121 DevicePath = NULL;
5122
5123 if (DefaultResults != NULL) {
5124 Status = MergeDefaultString (&AccessResults, DefaultResults);
5125 ASSERT_EFI_ERROR (Status);
5126 FreePool (DefaultResults);
5127 DefaultResults = NULL;
5128 }
5129
5130NextConfigString:
5131 if (!FirstElement) {
5132 Status = AppendToMultiString (Results, L"&");
5133 ASSERT_EFI_ERROR (Status);
5134 }
5135
5136 Status = AppendToMultiString (Results, AccessResults);
5137 ASSERT_EFI_ERROR (Status);
5138
5139 FirstElement = FALSE;
5140
5141 FreePool (AccessResults);
5142 AccessResults = NULL;
5143 FreePool (ConfigRequest);
5144 ConfigRequest = NULL;
5145
5146 //
5147 // Go to next <ConfigRequest> (skip '&').
5148 //
5149 StringPtr += Length;
5150 if (*StringPtr == 0) {
5151 *Progress = StringPtr;
5152 break;
5153 }
5154
5155 StringPtr++;
5156 }
5157
5158Done:
5159 if (EFI_ERROR (Status)) {
5160 FreePool (*Results);
5161 *Results = NULL;
5162 }
5163
5164 if (ConfigRequest != NULL) {
5165 FreePool (ConfigRequest);
5166 }
5167
5168 if (AccessResults != NULL) {
5169 FreePool (AccessResults);
5170 }
5171
5172 if (DefaultResults != NULL) {
5173 FreePool (DefaultResults);
5174 }
5175
5176 if (DevicePath != NULL) {
5177 FreePool (DevicePath);
5178 }
5179
5180 return Status;
5181}
5182
5205EFI_STATUS
5206EFIAPI
5208 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5209 OUT EFI_STRING *Results
5210 )
5211{
5212 EFI_STATUS Status;
5213 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
5214 EFI_STRING AccessResults;
5215 EFI_STRING Progress;
5216 EFI_STRING StringPtr;
5217 EFI_STRING ConfigRequest;
5218 UINTN Index;
5219 EFI_HANDLE *ConfigAccessHandles;
5220 UINTN NumberConfigAccessHandles;
5221 BOOLEAN FirstElement;
5222 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
5223 EFI_HII_HANDLE HiiHandle;
5224 EFI_STRING DefaultResults;
5226 LIST_ENTRY *Link;
5227 HII_DATABASE_RECORD *Database;
5228 UINT8 *DevicePathPkg;
5229 UINT8 *CurrentDevicePath;
5230 BOOLEAN IfrDataParsedFlag;
5231
5232 if ((This == NULL) || (Results == NULL)) {
5233 return EFI_INVALID_PARAMETER;
5234 }
5235
5237
5238 //
5239 // Allocate a fix length of memory to store Results. Reallocate memory for
5240 // Results if this fix length is insufficient.
5241 //
5242 *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
5243 if (*Results == NULL) {
5244 return EFI_OUT_OF_RESOURCES;
5245 }
5246
5247 NumberConfigAccessHandles = 0;
5248 Status = gBS->LocateHandleBuffer (
5249 ByProtocol,
5250 &gEfiHiiConfigAccessProtocolGuid,
5251 NULL,
5252 &NumberConfigAccessHandles,
5253 &ConfigAccessHandles
5254 );
5255 if (EFI_ERROR (Status)) {
5256 return Status;
5257 }
5258
5259 FirstElement = TRUE;
5260
5261 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
5262 Status = gBS->HandleProtocol (
5263 ConfigAccessHandles[Index],
5264 &gEfiHiiConfigAccessProtocolGuid,
5265 (VOID **)&ConfigAccess
5266 );
5267 if (EFI_ERROR (Status)) {
5268 continue;
5269 }
5270
5271 //
5272 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5273 //
5274 IfrDataParsedFlag = FALSE;
5275 Progress = NULL;
5276 HiiHandle = NULL;
5277 DefaultResults = NULL;
5278 Database = NULL;
5279 ConfigRequest = NULL;
5280 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
5281 if (DevicePath != NULL) {
5282 for (Link = Private->DatabaseList.ForwardLink;
5283 Link != &Private->DatabaseList;
5284 Link = Link->ForwardLink
5285 )
5286 {
5287 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
5288 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
5289 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
5290 if (CompareMem (
5291 DevicePath,
5292 CurrentDevicePath,
5293 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath)
5294 ) == 0)
5295 {
5296 HiiHandle = Database->Handle;
5297 break;
5298 }
5299 }
5300 }
5301 }
5302
5303 Status = ConfigAccess->ExtractConfig (
5304 ConfigAccess,
5305 NULL,
5306 &Progress,
5307 &AccessResults
5308 );
5309 if (EFI_ERROR (Status)) {
5310 //
5311 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5312 //
5313 if ((HiiHandle != NULL) && (DevicePath != NULL)) {
5314 IfrDataParsedFlag = TRUE;
5315 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
5316 //
5317 // Get the full request string to get the Current setting again.
5318 //
5319 if (!EFI_ERROR (Status) && (ConfigRequest != NULL)) {
5320 Status = ConfigAccess->ExtractConfig (
5321 ConfigAccess,
5322 ConfigRequest,
5323 &Progress,
5324 &AccessResults
5325 );
5326 FreePool (ConfigRequest);
5327 } else {
5328 Status = EFI_NOT_FOUND;
5329 }
5330 }
5331 }
5332
5333 if (!EFI_ERROR (Status)) {
5334 //
5335 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5336 //
5337 if (!IfrDataParsedFlag && (HiiHandle != NULL) && (DevicePath != NULL)) {
5338 StringPtr = StrStr (AccessResults, L"&GUID=");
5339 if (StringPtr != NULL) {
5340 *StringPtr = 0;
5341 }
5342
5343 if (InternalGetElementsFromRequest (AccessResults)) {
5344 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
5345 ASSERT_EFI_ERROR (Status);
5346 }
5347
5348 if (StringPtr != NULL) {
5349 *StringPtr = L'&';
5350 }
5351 }
5352
5353 //
5354 // Merge the default sting from IFR code into the got setting from driver.
5355 //
5356 if (DefaultResults != NULL) {
5357 Status = MergeDefaultString (&AccessResults, DefaultResults);
5358 ASSERT_EFI_ERROR (Status);
5359 FreePool (DefaultResults);
5360 DefaultResults = NULL;
5361 }
5362
5363 //
5364 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5365 // which separates the first <ConfigAltResp> and the following ones.
5366 //
5367 if (!FirstElement) {
5368 Status = AppendToMultiString (Results, L"&");
5369 ASSERT_EFI_ERROR (Status);
5370 }
5371
5372 Status = AppendToMultiString (Results, AccessResults);
5373 ASSERT_EFI_ERROR (Status);
5374
5375 FirstElement = FALSE;
5376
5377 FreePool (AccessResults);
5378 AccessResults = NULL;
5379 }
5380 }
5381
5382 FreePool (ConfigAccessHandles);
5383
5384 return EFI_SUCCESS;
5385}
5386
5412EFI_STATUS
5413EFIAPI
5415 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5416 IN CONST EFI_STRING Configuration,
5417 OUT EFI_STRING *Progress
5418 )
5419{
5421 EFI_STRING StringPtr;
5422 EFI_STRING ConfigResp;
5423 UINTN Length;
5424 EFI_STATUS Status;
5425 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
5426 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
5427 LIST_ENTRY *Link;
5428 HII_DATABASE_RECORD *Database;
5429 UINT8 *DevicePathPkg;
5430 UINT8 *CurrentDevicePath;
5431 EFI_HANDLE DriverHandle;
5432 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
5433 EFI_STRING AccessProgress;
5434 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
5435 BOOLEAN IsEfiVarstore;
5436 UINTN DevicePathSize;
5437
5438 if ((This == NULL) || (Progress == NULL)) {
5439 return EFI_INVALID_PARAMETER;
5440 }
5441
5442 if (Configuration == NULL) {
5443 *Progress = NULL;
5444 return EFI_INVALID_PARAMETER;
5445 }
5446
5448 StringPtr = Configuration;
5449 *Progress = StringPtr;
5450 Database = NULL;
5451 AccessProgress = NULL;
5452 EfiVarStoreInfo = NULL;
5453 IsEfiVarstore = FALSE;
5454
5455 //
5456 // The first element of <MultiConfigResp> should be
5457 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5458 //
5459 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
5460 return EFI_INVALID_PARAMETER;
5461 }
5462
5463 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) == 0) {
5464 //
5465 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5466 // or most recent & before the error.
5467 //
5468 if (StringPtr == Configuration) {
5469 *Progress = StringPtr;
5470 } else {
5471 *Progress = StringPtr - 1;
5472 }
5473
5474 //
5475 // Process each <ConfigResp> of <MultiConfigResp>
5476 //
5477 Length = CalculateConfigStringLen (StringPtr);
5478 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
5479 if (ConfigResp == NULL) {
5480 return EFI_OUT_OF_RESOURCES;
5481 }
5482
5483 //
5484 // Append '\0' to the end of ConfigRequest
5485 //
5486 *(ConfigResp + Length) = 0;
5487
5488 //
5489 // Get the UEFI device path
5490 //
5491 Status = GetDevicePath (ConfigResp, (UINT8 **)&DevicePath);
5492 if (EFI_ERROR (Status)) {
5493 FreePool (ConfigResp);
5494 return Status;
5495 }
5496
5497 //
5498 // Find driver which matches the routing data.
5499 //
5500 DriverHandle = NULL;
5501 for (Link = Private->DatabaseList.ForwardLink;
5502 Link != &Private->DatabaseList;
5503 Link = Link->ForwardLink
5504 )
5505 {
5506 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
5507
5508 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
5509 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
5510 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
5511 if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigResp)) {
5512 DriverHandle = Database->DriverHandle;
5513 break;
5514 }
5515 }
5516 }
5517
5518 //
5519 // Try to find driver handle by device path.
5520 //
5521 if (DriverHandle == NULL) {
5522 TempDevicePath = DevicePath;
5523 Status = gBS->LocateDevicePath (
5525 &TempDevicePath,
5526 &DriverHandle
5527 );
5528 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
5529 //
5530 // Routing data does not match any known driver.
5531 // Set Progress to the 'G' in "GUID" of the routing header.
5532 //
5533 FreePool (DevicePath);
5534 *Progress = StringPtr;
5535 FreePool (ConfigResp);
5536 return EFI_NOT_FOUND;
5537 }
5538 }
5539
5540 FreePool (DevicePath);
5541
5542 //
5543 // Check whether this ConfigRequest is search from Efi varstore type storage.
5544 //
5545 Status = GetVarStoreType (Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
5546 if (EFI_ERROR (Status)) {
5547 return Status;
5548 }
5549
5550 if (IsEfiVarstore) {
5551 //
5552 // Call the SetVariable function to route settings.
5553 //
5554 Status = RouteConfigRespForEfiVarStore (This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
5555 FreePool (EfiVarStoreInfo);
5556 } else {
5557 //
5558 // Call corresponding ConfigAccess protocol to route settings
5559 //
5560 Status = gBS->HandleProtocol (
5561 DriverHandle,
5562 &gEfiHiiConfigAccessProtocolGuid,
5563 (VOID **)&ConfigAccess
5564 );
5565 if (EFI_ERROR (Status)) {
5566 *Progress = StringPtr;
5567 FreePool (ConfigResp);
5568 return EFI_NOT_FOUND;
5569 }
5570
5571 Status = ConfigAccess->RouteConfig (
5572 ConfigAccess,
5573 ConfigResp,
5574 &AccessProgress
5575 );
5576 }
5577
5578 if (EFI_ERROR (Status)) {
5579 ASSERT (AccessProgress != NULL);
5580 //
5581 // AccessProgress indicates the parsing progress on <ConfigResp>.
5582 // Map it to the progress on <MultiConfigResp> then return it.
5583 //
5584 *Progress = StrStr (StringPtr, AccessProgress);
5585
5586 FreePool (ConfigResp);
5587 return Status;
5588 }
5589
5590 FreePool (ConfigResp);
5591 ConfigResp = NULL;
5592
5593 //
5594 // Go to next <ConfigResp> (skip '&').
5595 //
5596 StringPtr += Length;
5597 if (*StringPtr == 0) {
5598 *Progress = StringPtr;
5599 break;
5600 }
5601
5602 StringPtr++;
5603 }
5604
5605 return EFI_SUCCESS;
5606}
5607
5643EFI_STATUS
5644EFIAPI
5646 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5647 IN CONST EFI_STRING ConfigRequest,
5648 IN CONST UINT8 *Block,
5649 IN CONST UINTN BlockSize,
5650 OUT EFI_STRING *Config,
5651 OUT EFI_STRING *Progress
5652 )
5653{
5655 EFI_STRING StringPtr;
5656 UINTN Length;
5657 EFI_STATUS Status;
5658 EFI_STRING TmpPtr;
5659 UINT8 *TmpBuffer;
5660 UINTN Offset;
5661 UINTN Width;
5662 UINT8 *Value;
5663 EFI_STRING ValueStr;
5664 EFI_STRING ConfigElement;
5665 UINTN Index;
5666 UINT8 *TemBuffer;
5667 CHAR16 *TemString;
5668 CHAR16 TemChar;
5669
5670 TmpBuffer = NULL;
5671
5672 if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {
5673 return EFI_INVALID_PARAMETER;
5674 }
5675
5676 if ((Block == NULL) || (ConfigRequest == NULL)) {
5677 *Progress = ConfigRequest;
5678 return EFI_INVALID_PARAMETER;
5679 }
5680
5682 ASSERT (Private != NULL);
5683
5684 StringPtr = ConfigRequest;
5685 ValueStr = NULL;
5686 Value = NULL;
5687 ConfigElement = NULL;
5688
5689 //
5690 // Allocate a fix length of memory to store Results. Reallocate memory for
5691 // Results if this fix length is insufficient.
5692 //
5693 *Config = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
5694 if (*Config == NULL) {
5695 return EFI_OUT_OF_RESOURCES;
5696 }
5697
5698 //
5699 // Jump <ConfigHdr>
5700 //
5701 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
5702 *Progress = StringPtr;
5703 Status = EFI_INVALID_PARAMETER;
5704 goto Exit;
5705 }
5706
5707 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", L_STR_LEN (L"PATH=")) != 0) {
5708 StringPtr++;
5709 }
5710
5711 if (*StringPtr == 0) {
5712 *Progress = StringPtr - 1;
5713 Status = EFI_INVALID_PARAMETER;
5714 goto Exit;
5715 }
5716
5717 while (*StringPtr != L'&' && *StringPtr != 0) {
5718 StringPtr++;
5719 }
5720
5721 if (*StringPtr == 0) {
5722 *Progress = StringPtr;
5723
5724 AppendToMultiString (Config, ConfigRequest);
5725 HiiToLower (*Config);
5726
5727 return EFI_SUCCESS;
5728 }
5729
5730 //
5731 // Skip '&'
5732 //
5733 StringPtr++;
5734
5735 //
5736 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5737 //
5738 TemChar = *StringPtr;
5739 *StringPtr = '\0';
5740 AppendToMultiString (Config, ConfigRequest);
5741 *StringPtr = TemChar;
5742
5743 //
5744 // Parse each <RequestElement> if exists
5745 // Only <BlockName> format is supported by this help function.
5746 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5747 //
5748 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", L_STR_LEN (L"OFFSET=")) == 0) {
5749 //
5750 // Back up the header of one <BlockName>
5751 //
5752 TmpPtr = StringPtr;
5753
5754 StringPtr += L_STR_LEN (L"OFFSET=");
5755 //
5756 // Get Offset
5757 //
5758 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5759 if (EFI_ERROR (Status)) {
5760 *Progress = TmpPtr - 1;
5761 goto Exit;
5762 }
5763
5764 Offset = 0;
5765 CopyMem (
5766 &Offset,
5767 TmpBuffer,
5768 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5769 );
5770 FreePool (TmpBuffer);
5771
5772 StringPtr += Length;
5773 if (StrnCmp (StringPtr, L"&WIDTH=", L_STR_LEN (L"&WIDTH=")) != 0) {
5774 *Progress = TmpPtr - 1;
5775 Status = EFI_INVALID_PARAMETER;
5776 goto Exit;
5777 }
5778
5779 StringPtr += L_STR_LEN (L"&WIDTH=");
5780
5781 //
5782 // Get Width
5783 //
5784 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5785 if (EFI_ERROR (Status)) {
5786 *Progress = TmpPtr - 1;
5787 goto Exit;
5788 }
5789
5790 Width = 0;
5791 CopyMem (
5792 &Width,
5793 TmpBuffer,
5794 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5795 );
5796 FreePool (TmpBuffer);
5797
5798 StringPtr += Length;
5799 if ((*StringPtr != 0) && (*StringPtr != L'&')) {
5800 *Progress = TmpPtr - 1;
5801 Status = EFI_INVALID_PARAMETER;
5802 goto Exit;
5803 }
5804
5805 //
5806 // Calculate Value and convert it to hex string.
5807 //
5808 if (Offset + Width > BlockSize) {
5809 *Progress = StringPtr;
5810 Status = EFI_DEVICE_ERROR;
5811 goto Exit;
5812 }
5813
5814 Value = (UINT8 *)AllocateZeroPool (Width);
5815 if (Value == NULL) {
5816 *Progress = ConfigRequest;
5817 Status = EFI_OUT_OF_RESOURCES;
5818 goto Exit;
5819 }
5820
5821 CopyMem (Value, (UINT8 *)Block + Offset, Width);
5822
5823 Length = Width * 2 + 1;
5824 ValueStr = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
5825 if (ValueStr == NULL) {
5826 *Progress = ConfigRequest;
5827 Status = EFI_OUT_OF_RESOURCES;
5828 goto Exit;
5829 }
5830
5831 TemString = ValueStr;
5832 TemBuffer = Value + Width - 1;
5833 for (Index = 0; Index < Width; Index++, TemBuffer--) {
5834 UnicodeValueToStringS (
5835 TemString,
5836 Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
5837 PREFIX_ZERO | RADIX_HEX,
5838 *TemBuffer,
5839 2
5840 );
5841 TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
5842 }
5843
5844 FreePool (Value);
5845 Value = NULL;
5846
5847 //
5848 // Build a ConfigElement
5849 //
5850 Length += StringPtr - TmpPtr + 1 + L_STR_LEN (L"VALUE=");
5851 ConfigElement = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
5852 if (ConfigElement == NULL) {
5853 Status = EFI_OUT_OF_RESOURCES;
5854 goto Exit;
5855 }
5856
5857 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
5858 if (*StringPtr == 0) {
5859 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
5860 }
5861
5862 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
5863 StrCatS (ConfigElement, Length, L"VALUE=");
5864 StrCatS (ConfigElement, Length, ValueStr);
5865
5866 AppendToMultiString (Config, ConfigElement);
5867
5868 FreePool (ConfigElement);
5869 FreePool (ValueStr);
5870 ConfigElement = NULL;
5871 ValueStr = NULL;
5872
5873 //
5874 // If '\0', parsing is finished. Otherwise skip '&' to continue
5875 //
5876 if (*StringPtr == 0) {
5877 break;
5878 }
5879
5880 AppendToMultiString (Config, L"&");
5881 StringPtr++;
5882 }
5883
5884 if (*StringPtr != 0) {
5885 *Progress = StringPtr - 1;
5886 Status = EFI_INVALID_PARAMETER;
5887 goto Exit;
5888 }
5889
5890 HiiToLower (*Config);
5891 *Progress = StringPtr;
5892 return EFI_SUCCESS;
5893
5894Exit:
5895 if (*Config != NULL) {
5896 FreePool (*Config);
5897 *Config = NULL;
5898 }
5899
5900 if (ValueStr != NULL) {
5901 FreePool (ValueStr);
5902 }
5903
5904 if (Value != NULL) {
5905 FreePool (Value);
5906 }
5907
5908 if (ConfigElement != NULL) {
5909 FreePool (ConfigElement);
5910 }
5911
5912 return Status;
5913}
5914
5962EFI_STATUS
5963EFIAPI
5965 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5966 IN CONST EFI_STRING ConfigResp,
5967 IN OUT UINT8 *Block,
5968 IN OUT UINTN *BlockSize,
5969 OUT EFI_STRING *Progress
5970 )
5971{
5973 EFI_STRING StringPtr;
5974 EFI_STRING TmpPtr;
5975 UINTN Length;
5976 EFI_STATUS Status;
5977 UINT8 *TmpBuffer;
5978 UINTN Offset;
5979 UINTN Width;
5980 UINT8 *Value;
5981 UINTN BufferSize;
5982 UINTN MaxBlockSize;
5983
5984 TmpBuffer = NULL;
5985
5986 if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {
5987 return EFI_INVALID_PARAMETER;
5988 }
5989
5990 *Progress = ConfigResp;
5991 if (ConfigResp == NULL) {
5992 return EFI_INVALID_PARAMETER;
5993 }
5994
5996 ASSERT (Private != NULL);
5997
5998 StringPtr = ConfigResp;
5999 BufferSize = *BlockSize;
6000 Value = NULL;
6001 MaxBlockSize = 0;
6002
6003 //
6004 // Jump <ConfigHdr>
6005 //
6006 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
6007 *Progress = StringPtr;
6008 Status = EFI_INVALID_PARAMETER;
6009 goto Exit;
6010 }
6011
6012 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", L_STR_LEN (L"PATH=")) != 0) {
6013 StringPtr++;
6014 }
6015
6016 if (*StringPtr == 0) {
6017 *Progress = StringPtr;
6018 Status = EFI_INVALID_PARAMETER;
6019 goto Exit;
6020 }
6021
6022 while (*StringPtr != L'&' && *StringPtr != 0) {
6023 StringPtr++;
6024 }
6025
6026 if (*StringPtr == 0) {
6027 *Progress = StringPtr;
6028 Status = EFI_INVALID_PARAMETER;
6029 goto Exit;
6030 }
6031
6032 //
6033 // Parse each <ConfigElement> if exists
6034 // Only '&'<BlockConfig> format is supported by this help function.
6035 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
6036 //
6037 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", L_STR_LEN (L"&OFFSET=")) == 0) {
6038 TmpPtr = StringPtr;
6039 StringPtr += L_STR_LEN (L"&OFFSET=");
6040 //
6041 // Get Offset
6042 //
6043 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
6044 if (EFI_ERROR (Status)) {
6045 *Progress = TmpPtr;
6046 goto Exit;
6047 }
6048
6049 Offset = 0;
6050 CopyMem (
6051 &Offset,
6052 TmpBuffer,
6053 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
6054 );
6055 FreePool (TmpBuffer);
6056
6057 StringPtr += Length;
6058 if (StrnCmp (StringPtr, L"&WIDTH=", L_STR_LEN (L"&WIDTH=")) != 0) {
6059 *Progress = TmpPtr;
6060 Status = EFI_INVALID_PARAMETER;
6061 goto Exit;
6062 }
6063
6064 StringPtr += L_STR_LEN (L"&WIDTH=");
6065
6066 //
6067 // Get Width
6068 //
6069 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
6070 if (EFI_ERROR (Status)) {
6071 *Progress = TmpPtr;
6072 goto Exit;
6073 }
6074
6075 Width = 0;
6076 CopyMem (
6077 &Width,
6078 TmpBuffer,
6079 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
6080 );
6081 FreePool (TmpBuffer);
6082
6083 StringPtr += Length;
6084 if (StrnCmp (StringPtr, L"&VALUE=", L_STR_LEN (L"&VALUE=")) != 0) {
6085 *Progress = TmpPtr;
6086 Status = EFI_INVALID_PARAMETER;
6087 goto Exit;
6088 }
6089
6090 StringPtr += L_STR_LEN (L"&VALUE=");
6091
6092 //
6093 // Get Value
6094 //
6095 Status = GetValueOfNumber (StringPtr, &Value, &Length);
6096 if (EFI_ERROR (Status)) {
6097 *Progress = TmpPtr;
6098 goto Exit;
6099 }
6100
6101 StringPtr += Length;
6102 if ((*StringPtr != 0) && (*StringPtr != L'&')) {
6103 *Progress = TmpPtr;
6104 Status = EFI_INVALID_PARAMETER;
6105 goto Exit;
6106 }
6107
6108 //
6109 // Update the Block with configuration info
6110 //
6111 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
6112 CopyMem (Block + Offset, Value, Width);
6113 }
6114
6115 if (Offset + Width > MaxBlockSize) {
6116 MaxBlockSize = Offset + Width;
6117 }
6118
6119 FreePool (Value);
6120 Value = NULL;
6121
6122 //
6123 // If '\0', parsing is finished.
6124 //
6125 if (*StringPtr == 0) {
6126 break;
6127 }
6128 }
6129
6130 //
6131 // The input string is not ConfigResp format, return error.
6132 //
6133 if (*StringPtr != 0) {
6134 *Progress = StringPtr;
6135 Status = EFI_INVALID_PARAMETER;
6136 goto Exit;
6137 }
6138
6139 *Progress = StringPtr + StrLen (StringPtr);
6140 *BlockSize = MaxBlockSize - 1;
6141
6142 if (MaxBlockSize > BufferSize) {
6143 *BlockSize = MaxBlockSize;
6144 if (Block != NULL) {
6145 return EFI_BUFFER_TOO_SMALL;
6146 }
6147 }
6148
6149 if (Block == NULL) {
6150 *Progress = ConfigResp;
6151 return EFI_INVALID_PARAMETER;
6152 }
6153
6154 return EFI_SUCCESS;
6155
6156Exit:
6157
6158 if (Value != NULL) {
6159 FreePool (Value);
6160 }
6161
6162 return Status;
6163}
6164
6205EFI_STATUS
6206EFIAPI
6208 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
6209 IN CONST EFI_STRING Configuration,
6210 IN CONST EFI_GUID *Guid,
6211 IN CONST EFI_STRING Name,
6212 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
6213 IN CONST UINT16 *AltCfgId,
6214 OUT EFI_STRING *AltCfgResp
6215 )
6216{
6217 EFI_STATUS Status;
6218 EFI_STRING StringPtr;
6219 EFI_STRING HdrStart;
6220 EFI_STRING HdrEnd;
6221 EFI_STRING TmpPtr;
6222 UINTN Length;
6223 EFI_STRING GuidStr;
6224 EFI_STRING NameStr;
6225 EFI_STRING PathStr;
6226 EFI_STRING AltIdStr;
6227 EFI_STRING Result;
6228 BOOLEAN GuidFlag;
6229 BOOLEAN NameFlag;
6230 BOOLEAN PathFlag;
6231
6232 HdrStart = NULL;
6233 HdrEnd = NULL;
6234 GuidStr = NULL;
6235 NameStr = NULL;
6236 PathStr = NULL;
6237 AltIdStr = NULL;
6238 Result = NULL;
6239 GuidFlag = FALSE;
6240 NameFlag = FALSE;
6241 PathFlag = FALSE;
6242
6243 if ((This == NULL) || (Configuration == NULL) || (AltCfgResp == NULL)) {
6244 return EFI_INVALID_PARAMETER;
6245 }
6246
6247 StringPtr = Configuration;
6248 if (StrnCmp (StringPtr, L"GUID=", L_STR_LEN (L"GUID=")) != 0) {
6249 return EFI_INVALID_PARAMETER;
6250 }
6251
6252 //
6253 // Generate the sub string for later matching.
6254 //
6255 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)Guid, 1, &GuidStr);
6257 L"PATH=",
6258 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
6259 (VOID *)DevicePath,
6260 1,
6261 &PathStr
6262 );
6263 if (AltCfgId != NULL) {
6264 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *)AltCfgId, 3, &AltIdStr);
6265 }
6266
6267 if (Name != NULL) {
6268 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
6269 } else {
6270 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
6271 }
6272
6273 while (*StringPtr != 0) {
6274 //
6275 // Try to match the GUID
6276 //
6277 if (!GuidFlag) {
6278 TmpPtr = StrStr (StringPtr, GuidStr);
6279 if (TmpPtr == NULL) {
6280 Status = EFI_NOT_FOUND;
6281 goto Exit;
6282 }
6283
6284 HdrStart = TmpPtr;
6285
6286 //
6287 // Jump to <NameHdr>
6288 //
6289 if (Guid != NULL) {
6290 StringPtr = TmpPtr + StrLen (GuidStr);
6291 } else {
6292 StringPtr = StrStr (TmpPtr, L"NAME=");
6293 if (StringPtr == NULL) {
6294 Status = EFI_NOT_FOUND;
6295 goto Exit;
6296 }
6297 }
6298
6299 GuidFlag = TRUE;
6300 }
6301
6302 //
6303 // Try to match the NAME
6304 //
6305 if (GuidFlag && !NameFlag) {
6306 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
6307 GuidFlag = FALSE;
6308 } else {
6309 //
6310 // Jump to <PathHdr>
6311 //
6312 if (Name != NULL) {
6313 StringPtr += StrLen (NameStr);
6314 } else {
6315 StringPtr = StrStr (StringPtr, L"PATH=");
6316 if (StringPtr == NULL) {
6317 Status = EFI_NOT_FOUND;
6318 goto Exit;
6319 }
6320 }
6321
6322 NameFlag = TRUE;
6323 }
6324 }
6325
6326 //
6327 // Try to match the DevicePath
6328 //
6329 if (GuidFlag && NameFlag && !PathFlag) {
6330 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
6331 GuidFlag = FALSE;
6332 NameFlag = FALSE;
6333 } else {
6334 //
6335 // Jump to '&' before <DescHdr> or <ConfigBody>
6336 //
6337 if (DevicePath != NULL) {
6338 StringPtr += StrLen (PathStr);
6339 } else {
6340 StringPtr = StrStr (StringPtr, L"&");
6341 if (StringPtr == NULL) {
6342 Status = EFI_NOT_FOUND;
6343 goto Exit;
6344 }
6345
6346 StringPtr++;
6347 }
6348
6349 PathFlag = TRUE;
6350 HdrEnd = StringPtr;
6351 }
6352 }
6353
6354 //
6355 // Try to match the AltCfgId
6356 //
6357 if (GuidFlag && NameFlag && PathFlag) {
6358 if (AltCfgId == NULL) {
6359 //
6360 // Return Current Setting when AltCfgId is NULL.
6361 //
6362 Status = OutputConfigBody (StringPtr, &Result);
6363 goto Exit;
6364 }
6365
6366 //
6367 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6368 //
6369 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
6370 GuidFlag = FALSE;
6371 NameFlag = FALSE;
6372 PathFlag = FALSE;
6373 } else {
6374 //
6375 // Skip AltIdStr and &
6376 //
6377 StringPtr = StringPtr + StrLen (AltIdStr);
6378 Status = OutputConfigBody (StringPtr, &Result);
6379 goto Exit;
6380 }
6381 }
6382 }
6383
6384 Status = EFI_NOT_FOUND;
6385
6386Exit:
6387 *AltCfgResp = NULL;
6388 if (!EFI_ERROR (Status) && (Result != NULL)) {
6389 //
6390 // Copy the <ConfigHdr> and <ConfigBody>
6391 //
6392 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
6393 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
6394 if (*AltCfgResp == NULL) {
6395 Status = EFI_OUT_OF_RESOURCES;
6396 } else {
6397 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
6398 StrCatS (*AltCfgResp, Length, Result);
6399 Status = EFI_SUCCESS;
6400 }
6401 }
6402
6403 if (GuidStr != NULL) {
6404 FreePool (GuidStr);
6405 }
6406
6407 if (NameStr != NULL) {
6408 FreePool (NameStr);
6409 }
6410
6411 if (PathStr != NULL) {
6412 FreePool (PathStr);
6413 }
6414
6415 if (AltIdStr != NULL) {
6416 FreePool (AltIdStr);
6417 }
6418
6419 if (Result != NULL) {
6420 FreePool (Result);
6421 }
6422
6423 return Status;
6424}
UINT16 BlockSize
Definition Apm.h:32
UINT64 Length
VOID EFIAPI Exit(IN EFI_STATUS Status)
EFI_STATUS RouteConfigRespForEfiVarStore(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, IN EFI_STRING RequestResp, OUT EFI_STRING *Result)
VOID UpdateDefaultValue(IN LIST_ENTRY *BlockLink)
EFI_STRING InternalGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId)
CHAR8 * GetSupportedLanguages(IN EFI_HII_HANDLE HiiHandle)
IFR_BLOCK_DATA * GetNameElement(IN EFI_STRING ConfigRequest, OUT EFI_STRING *Progress)
EFI_STATUS EFIAPI HiiConfigRoutingExportConfig(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, OUT EFI_STRING *Results)
BOOLEAN InternalGetElementsFromRequest(IN EFI_STRING ConfigRequest)
EFI_STATUS CompareBlockElementDefault(IN EFI_STRING DefaultAltCfgResp, IN OUT EFI_STRING *ConfigAltResp, IN EFI_STRING AltConfigHdr, IN OUT BOOLEAN *ConfigAltRespChanged)
EFI_STATUS FindSameBlockElement(IN EFI_STRING String, IN EFI_STRING BlockName, IN UINT8 *Buffer, OUT BOOLEAN *Found, IN UINTN BufferLen)
BOOLEAN GenerateConfigRequest(IN CHAR16 *ConfigHdr, IN IFR_VARSTORAGE_DATA *VarStorageData, OUT EFI_STATUS *Status, IN OUT EFI_STRING *ConfigRequest)
IFR_BLOCK_DATA * GetBlockElement(IN EFI_STRING ConfigRequest, OUT EFI_STRING *Progress)
EFI_STATUS AppendToMultiString(IN OUT EFI_STRING *MultiString, IN EFI_STRING AppendString)
BOOLEAN IsThisVarstore(IN EFI_GUID *VarstoreGuid, IN CHAR16 *Name, IN CHAR16 *ConfigHdr)
EFI_STATUS EFIAPI HiiGetAltCfg(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING Configuration, IN CONST EFI_GUID *Guid, IN CONST EFI_STRING Name, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST UINT16 *AltCfgId, OUT EFI_STRING *AltCfgResp)
EFI_STATUS CompareNameElementDefault(IN EFI_STRING DefaultAltCfgResp, IN OUT EFI_STRING *ConfigAltResp, IN EFI_STRING AltConfigHdr, IN OUT BOOLEAN *ConfigAltRespChanged)
CHAR16 * OffsetWidthValidate(CHAR16 *ConfigElements)
EFI_STATUS IsThisOpcodeRequired(IN IFR_BLOCK_DATA *RequestBlockArray, IN EFI_HII_HANDLE HiiHandle, IN OUT IFR_VARSTORAGE_DATA *VarStorageData, IN EFI_IFR_OP_HEADER *IfrOpHdr, IN UINT16 VarWidth, OUT IFR_BLOCK_DATA **ReturnData, IN BOOLEAN IsBitVar)
EFI_STATUS EFIAPI ParseIfrData(IN EFI_HII_HANDLE HiiHandle, IN UINT8 *Package, IN UINT32 PackageLength, IN EFI_STRING ConfigHdr, IN IFR_BLOCK_DATA *RequestBlockArray, IN OUT IFR_VARSTORAGE_DATA *VarStorageData, OUT IFR_DEFAULT_DATA *DefaultIdArray)
BOOLEAN IsThisPackageList(IN HII_DATABASE_RECORD *DataBaseRecord, IN EFI_STRING ConfigHdr)
VOID GenerateSubStr(IN CONST EFI_STRING String, IN UINTN BufferLen, IN VOID *Buffer, IN UINT8 Flag, OUT EFI_STRING *SubStr)
EFI_STATUS EFIAPI HiiConfigRoutingRouteConfig(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress)
EFI_STATUS GetVarStoreType(IN HII_DATABASE_RECORD *DataBaseRecord, IN EFI_STRING ConfigHdr, OUT BOOLEAN *IsEfiVarstore, OUT EFI_IFR_VARSTORE_EFI **EfiVarStore)
VOID InsertBlockData(IN LIST_ENTRY *BlockLink, IN IFR_BLOCK_DATA **BlockData)
CHAR16 * NameValueValidate(CHAR16 *ConfigElements)
VOID UpdateBlockDataArray(IN LIST_ENTRY *BlockLink)
VOID EFIAPI HiiToLower(IN EFI_STRING ConfigString)
BOOLEAN InternalBlockArrayCheck(IN IFR_BLOCK_DATA *RequestBlockArray, IN UINT16 VarOffset, IN UINT16 VarWidth, IN BOOLEAN IsNameValueType, IN EFI_HII_HANDLE HiiHandle)
EFI_STATUS GenerateHdr(IN IFR_VARSTORAGE_DATA *VarStorageData, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT EFI_STRING *ConfigHdr)
EFI_STATUS EFIAPI HiiConfigRoutingExtractConfig(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING Request, OUT EFI_STRING *Progress, OUT EFI_STRING *Results)
EFI_STATUS GetConfigRespFromEfiVarStore(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo, IN EFI_STRING Request, OUT EFI_STRING *RequestResp, OUT EFI_STRING *AccessProgress)
EFI_STATUS EFIAPI GetFullStringFromHiiFormPackages(IN HII_DATABASE_RECORD *DataBaseRecord, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN OUT EFI_STRING *Request, IN OUT EFI_STRING *AltCfgResp, OUT EFI_STRING *PointerProgress OPTIONAL)
EFI_STATUS EFIAPI HiiBlockToConfig(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING ConfigRequest, IN CONST UINT8 *Block, IN CONST UINTN BlockSize, OUT EFI_STRING *Config, OUT EFI_STRING *Progress)
EFI_STATUS OutputConfigBody(IN EFI_STRING String, OUT EFI_STRING *ConfigBody)
EFI_STATUS CompareAndMergeDefaultString(IN OUT EFI_STRING *AltCfgResp, IN EFI_STRING DefaultAltCfgResp, IN EFI_STRING AltConfigHdr)
EFI_STATUS GetDevicePath(IN EFI_STRING String, OUT UINT8 **DevicePathData)
EFI_STATUS GetValueOfNumber(IN EFI_STRING StringPtr, OUT UINT8 **Number, OUT UINTN *Len)
EFI_STATUS GenerateAltConfigResp(IN EFI_HII_HANDLE HiiHandle, IN CHAR16 *ConfigHdr, IN IFR_VARSTORAGE_DATA *VarStorageData, IN IFR_DEFAULT_DATA *DefaultIdArray, IN OUT EFI_STRING *DefaultAltCfgResp)
EFI_STATUS GetFormPackageData(IN HII_DATABASE_RECORD *DataBaseRecord, IN OUT UINT8 **HiiFormPackage, OUT UINTN *PackageSize)
CHAR16 * ConfigRequestValidate(CHAR16 *ConfigRequest)
VOID InsertDefaultValue(IN IFR_BLOCK_DATA *BlockData, IN IFR_DEFAULT_DATA *DefaultValueData)
UINTN CalculateConfigStringLen(IN EFI_STRING String)
HII_DATABASE_PRIVATE_DATA mPrivate
EFI_STATUS EFIAPI HiiConfigToBlock(IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING ConfigResp, IN OUT UINT8 *Block, IN OUT UINTN *BlockSize, OUT EFI_STRING *Progress)
EFI_STATUS EFIAPI MergeDefaultString(IN OUT EFI_STRING *AltCfgResp, IN EFI_STRING DefaultAltCfgResp)
VOID MergeBlockDefaultValue(IN OUT IFR_BLOCK_DATA *FirstBlock, IN OUT IFR_BLOCK_DATA *SecondBlock)
EFI_STATUS ExportFormPackages(IN HII_DATABASE_PRIVATE_DATA *Private, IN EFI_HII_HANDLE Handle, IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList, IN UINTN UsedSize, IN UINTN BufferSize, IN OUT VOID *Buffer, IN OUT UINTN *ResultSize)
Definition Database.c:1197
void Error(char *FileName, uint32_t LineNumber, uint32_t ErrorCode, char *OffendingText, char *MsgFmt,...)
Definition EfiLdrImage.c:57
#define EFI_HII_VARSTORE_BUFFER
#define EFI_HII_VARSTORE_NAME_VALUE
#define HII_DATABASE_RECORD_SIGNATURE
#define CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS(a)
#define MAX_STRING_LENGTH
Definition HiiDatabase.h:45
#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
@ DefaultValueFromFlag
@ DefaultValueFromDefault
Definition HiiDatabase.h:99
@ DefaultValueFromOpcode
@ DefaultValueFromOtherDefault
DMG_SIZE_DEVICE_PATH Size
EFI_BOOT_SERVICES * gBS
#define L_STR_LEN(String)
Definition OcStringLib.h:26
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)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
EFI_GUID gEfiDevicePathProtocolGuid
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
Definition UserMisc.c:680
#define ASSERT(x)
Definition coder.h:55
#define Len
Definition deflate.h:82
EFI_HII_STRING_PROTOCOL HiiString
HII_DATABASE_PACKAGE_LIST_INSTANCE * PackageList
EFI_HANDLE DriverHandle
EFI_HII_HANDLE Handle
BOOLEAN IsBitVar
Definition HiiDatabase.h:92
CHAR16 * Name
Definition HiiDatabase.h:91
LIST_ENTRY DefaultValueEntry
Definition HiiDatabase.h:90
EFI_QUESTION_ID QuestionId
Definition HiiDatabase.h:87
LIST_ENTRY Entry
Definition HiiDatabase.h:82
EFI_IFR_TYPE_VALUE Value
LIST_ENTRY Entry
DEFAULT_VALUE_TYPE Type
LIST_ENTRY BlockEntry
Definition HiiDatabase.h:78