TianoCore EDK2 master
Loading...
Searching...
No Matches
Support.c
Go to the documentation of this file.
1
9#include "MtrrLibUnitTest.h"
10
11MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = {
12 CacheUncacheable, CacheWriteCombining, CacheWriteThrough, CacheWriteProtected, CacheWriteBack
13};
14
15UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
16MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
17MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
20MSR_IA32_TME_ACTIVATE_REGISTER mTmeActivateMsr;
21CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx;
22CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX mCpuidExtendedFeatureFlagsEcx;
23CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax;
24
25BOOLEAN mRandomInput;
26UINTN mNumberIndex = 0;
27extern UINTN mNumbers[];
28extern UINTN mNumberCount;
29
40 VOID
41 )
42{
43 if (mRandomInput) {
44 return rand ();
45 } else {
46 return mNumbers[mNumberIndex++ % (mNumberCount - 1)];
47 }
48}
49
50CHAR8 mContentTemplate[] = {
51 "/** @file\n"
52 " Pre-generated random number used by MtrrLib test.\n"
53 "\n"
54 " Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\n"
55 " SPDX-License-Identifier: BSD-2-Clause-Patent\n"
56 "**/\n"
57 "UINTN mNumberCount = %d;\n"
58 "UINTN mNumbers[] = {"
59};
60
67VOID
69 CHAR8 *FilePath,
70 UINTN Count
71 )
72{
73 FILE *File;
74 UINTN Index;
75
76 File = fopen (FilePath, "w");
77 fprintf (File, mContentTemplate, Count);
78 for (Index = 0; Index < Count; Index++) {
79 if (Index % 10 == 0) {
80 fprintf (File, "\n ");
81 }
82
83 fprintf (File, " %d,", rand ());
84 }
85
86 fprintf (File, "\n};\n");
87 fclose (File);
88}
89
122UINT32
123EFIAPI
125 IN UINT32 Index,
126 IN UINT32 SubIndex,
127 OUT UINT32 *Eax OPTIONAL,
128 OUT UINT32 *Ebx OPTIONAL,
129 OUT UINT32 *Ecx OPTIONAL,
130 OUT UINT32 *Edx OPTIONAL
131 )
132{
133 switch (Index) {
134 case CPUID_SIGNATURE:
135 if (Eax != NULL) {
137 }
138
139 return Index;
140 break;
142 if (Edx != NULL) {
143 *Edx = mCpuidVersionInfoEdx.Uint32;
144 }
145
146 return Index;
147 break;
149 if (Ecx != NULL) {
150 *Ecx = mCpuidExtendedFeatureFlagsEcx.Uint32;
151 }
152
153 return Index;
154 break;
155 case CPUID_EXTENDED_FUNCTION:
156 if (Eax != NULL) {
157 *Eax = CPUID_VIR_PHY_ADDRESS_SIZE;
158 }
159
160 return Index;
161 break;
162 case CPUID_VIR_PHY_ADDRESS_SIZE:
163 if (Eax != NULL) {
164 *Eax = mCpuidVirPhyAddressSizeEax.Uint32;
165 }
166
167 return Index;
168 break;
169 }
170
171 //
172 // Should never fall through to here
173 //
174 ASSERT (FALSE);
175 return Index;
176}
177
203UINT32
204EFIAPI
206 IN UINT32 Index,
207 OUT UINT32 *Eax OPTIONAL,
208 OUT UINT32 *Ebx OPTIONAL,
209 OUT UINT32 *Ecx OPTIONAL,
210 OUT UINT32 *Edx OPTIONAL
211 )
212{
213 return UnitTestMtrrLibAsmCpuidEx (Index, 0, Eax, Ebx, Ecx, Edx);
214}
215
230UINT64
231EFIAPI
233 IN UINT32 MsrIndex
234 )
235{
236 UINT32 Index;
237
238 UT_ASSERT_EQUAL (mCpuidVersionInfoEdx.Bits.MTRR, 1);
239
240 for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
241 if (MsrIndex == mFixedMtrrsIndex[Index]) {
242 UT_ASSERT_EQUAL (mMtrrCapMsr.Bits.FIX, 1);
243 return mFixedMtrrsValue[Index];
244 }
245 }
246
247 if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
248 (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_MTRR << 1)))
249 {
250 UT_ASSERT_TRUE (((MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1) < mMtrrCapMsr.Bits.VCNT);
251 if (MsrIndex % 2 == 0) {
252 Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
253 return mVariableMtrrsPhysBase[Index].Uint64;
254 } else {
255 Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
256 return mVariableMtrrsPhysMask[Index].Uint64;
257 }
258 }
259
260 if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
261 return mDefTypeMsr.Uint64;
262 }
263
264 if (MsrIndex == MSR_IA32_MTRRCAP) {
265 return mMtrrCapMsr.Uint64;
266 }
267
268 if (MsrIndex == MSR_IA32_TME_ACTIVATE) {
269 return mTmeActivateMsr.Uint64;
270 }
271
272 //
273 // Should never fall through to here
274 //
275 ASSERT (FALSE);
276 return 0;
277}
278
296UINT64
297EFIAPI
299 IN UINT32 MsrIndex,
300 IN UINT64 Value
301 )
302{
303 UINT32 Index;
304
305 UT_ASSERT_EQUAL (mCpuidVersionInfoEdx.Bits.MTRR, 1);
306
307 for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
308 if (MsrIndex == mFixedMtrrsIndex[Index]) {
309 UT_ASSERT_EQUAL (mMtrrCapMsr.Bits.FIX, 1);
310 mFixedMtrrsValue[Index] = Value;
311 return Value;
312 }
313 }
314
315 if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
316 (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_MTRR << 1)))
317 {
318 UT_ASSERT_TRUE (((MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1) < mMtrrCapMsr.Bits.VCNT);
319 if (MsrIndex % 2 == 0) {
320 Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
321 mVariableMtrrsPhysBase[Index].Uint64 = Value;
322 return Value;
323 } else {
324 Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
325 mVariableMtrrsPhysMask[Index].Uint64 = Value;
326 return Value;
327 }
328 }
329
330 if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
331 if (((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&Value)->Bits.FE == 1) {
332 UT_ASSERT_EQUAL (mMtrrCapMsr.Bits.FIX, 1);
333 }
334
335 mDefTypeMsr.Uint64 = Value;
336 return Value;
337 }
338
339 if (MsrIndex == MSR_IA32_MTRRCAP) {
340 mMtrrCapMsr.Uint64 = Value;
341 return Value;
342 }
343
344 //
345 // Should never fall through to here
346 //
347 ASSERT (FALSE);
348 return 0;
349}
350
357EFIAPI
359 IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
360 )
361{
362 UINT32 Index;
363
364 SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), SystemParameter->DefaultCacheType);
365
366 for (Index = 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index++) {
367 mVariableMtrrsPhysBase[Index].Uint64 = 0;
368 mVariableMtrrsPhysMask[Index].Uint64 = 0;
369 }
370
371 mDefTypeMsr.Bits.E = 1;
372 mDefTypeMsr.Bits.FE = 0;
373 mDefTypeMsr.Bits.Type = SystemParameter->DefaultCacheType;
374 mDefTypeMsr.Bits.Reserved1 = 0;
375 mDefTypeMsr.Bits.Reserved2 = 0;
376 mDefTypeMsr.Bits.Reserved3 = 0;
377
378 mMtrrCapMsr.Bits.SMRR = 0;
379 mMtrrCapMsr.Bits.WC = 0;
380 mMtrrCapMsr.Bits.VCNT = SystemParameter->VariableMtrrCount;
381 mMtrrCapMsr.Bits.FIX = SystemParameter->FixedMtrrSupported;
382 mMtrrCapMsr.Bits.Reserved1 = 0;
383 mMtrrCapMsr.Bits.Reserved2 = 0;
384 mMtrrCapMsr.Bits.Reserved3 = 0;
385
386 mCpuidVersionInfoEdx.Bits.MTRR = SystemParameter->MtrrSupported;
387 mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits = SystemParameter->PhysicalAddressBits;
388
389 //
390 // Hook BaseLib functions used by MtrrLib that require some emulation.
391 //
394
397
398 if (SystemParameter->MkTmeKeyidBits != 0) {
399 mCpuidExtendedFeatureFlagsEcx.Bits.TME_EN = 1;
400 mTmeActivateMsr.Bits.TmeEnable = 1;
401 mTmeActivateMsr.Bits.MkTmeKeyidBits = SystemParameter->MkTmeKeyidBits;
402 } else {
403 mCpuidExtendedFeatureFlagsEcx.Bits.TME_EN = 0;
404 mTmeActivateMsr.Bits.TmeEnable = 0;
405 mTmeActivateMsr.Bits.MkTmeKeyidBits = 0;
406 }
407
408 return UNIT_TEST_PASSED;
409}
410
417EFIAPI
419 IN UNIT_TEST_CONTEXT Context
420 )
421{
423}
424
436VOID
438 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
439 IN UINT32 PhysicalAddressBits,
440 IN UINT32 VariableMtrrCount,
441 IN MTRR_SETTINGS *Mtrrs,
442 OUT MTRR_MEMORY_RANGE *Ranges,
443 IN OUT UINTN *RangeCount,
444 OUT UINT32 *MtrrCount
445 )
446{
447 UINTN Index;
448 UINT64 MtrrValidBitsMask;
449 UINT64 MtrrValidAddressMask;
450 MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
451
452 ASSERT (Mtrrs != NULL);
453 ASSERT (VariableMtrrCount <= ARRAY_SIZE (Mtrrs->Variables.Mtrr));
454
455 MtrrValidBitsMask = (1ull << PhysicalAddressBits) - 1;
456 MtrrValidAddressMask = MtrrValidBitsMask & ~0xFFFull;
457
458 *MtrrCount = 0;
459 for (Index = 0; Index < VariableMtrrCount; Index++) {
460 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V == 1) {
461 RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs->Variables.Mtrr[Index].Base & MtrrValidAddressMask;
462 RawMemoryRanges[*MtrrCount].Type =
463 ((MSR_IA32_MTRR_PHYSBASE_REGISTER *)&Mtrrs->Variables.Mtrr[Index].Base)->Bits.Type;
464 RawMemoryRanges[*MtrrCount].Length =
465 ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
466 (*MtrrCount)++;
467 }
468 }
469
470 GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemoryRanges, *MtrrCount, Ranges, RangeCount);
471}
472
480UINT32
482 UINT32 Start,
483 UINT32 Limit
484 )
485{
486 return (UINT32)(((double)Rand () / RAND_MAX) * (Limit - Start)) + Start;
487}
488
496UINT64
498 UINT64 Start,
499 UINT64 Limit
500 )
501{
502 return (UINT64)(((double)Rand () / RAND_MAX) * (Limit - Start)) + Start;
503}
504
513VOID
515 IN UINT32 PhysicalAddressBits,
516 IN MTRR_MEMORY_CACHE_TYPE CacheType,
517 OUT MTRR_VARIABLE_SETTING *MtrrPair OPTIONAL,
518 OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
519 )
520{
523 UINT32 SizeShift;
524 UINT32 BaseShift;
525 UINT64 RandomBoundary;
526 UINT64 MaxPhysicalAddress;
527 UINT64 RangeSize;
528 UINT64 RangeBase;
529 UINT64 PhysBasePhyMaskValidBitsMask;
530
531 MaxPhysicalAddress = 1ull << PhysicalAddressBits;
532 do {
533 SizeShift = Random32 (12, PhysicalAddressBits - 1);
534 RangeSize = 1ull << SizeShift;
535
536 BaseShift = Random32 (SizeShift, PhysicalAddressBits - 1);
537 RandomBoundary = Random64 (0, 1ull << (PhysicalAddressBits - BaseShift));
538 RangeBase = RandomBoundary << BaseShift;
539 } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1);
540
541 PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress - 1) & 0xfffffffffffff000ULL;
542
543 PhysBase.Uint64 = 0;
544 PhysBase.Bits.Type = CacheType;
545 PhysBase.Uint64 |= RangeBase & PhysBasePhyMaskValidBitsMask;
546 PhysMask.Uint64 = 0;
547 PhysMask.Bits.V = 1;
548 PhysMask.Uint64 |= ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsMask;
549
550 if (MtrrPair != NULL) {
551 MtrrPair->Base = PhysBase.Uint64;
552 MtrrPair->Mask = PhysMask.Uint64;
553 }
554
555 if (MtrrMemoryRange != NULL) {
556 MtrrMemoryRange->BaseAddress = RangeBase;
557 MtrrMemoryRange->Length = RangeSize;
558 MtrrMemoryRange->Type = CacheType;
559 }
560}
561
571BOOLEAN
573 IN MTRR_MEMORY_RANGE *Range,
574 IN MTRR_MEMORY_RANGE *Ranges,
575 IN UINTN Count
576 )
577{
578 while (Count-- != 0) {
579 //
580 // Two ranges overlap when:
581 // 1. range#2.base is in the middle of range#1
582 // 2. range#1.base is in the middle of range#2
583 //
584 if ( ((Range->BaseAddress <= Ranges[Count].BaseAddress) && (Ranges[Count].BaseAddress < Range->BaseAddress + Range->Length))
585 || ((Ranges[Count].BaseAddress <= Range->BaseAddress) && (Range->BaseAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)))
586 {
587 return TRUE;
588 }
589 }
590
591 return FALSE;
592}
593
605VOID
607 IN UINT32 PhysicalAddressBits,
608 IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
609 IN UINT32 UcCount,
610 IN UINT32 WtCount,
611 IN UINT32 WbCount,
612 IN UINT32 WpCount,
613 IN UINT32 WcCount
614 )
615{
616 UINT32 Index;
617
618 //
619 // 1. Generate UC, WT, WB in order.
620 //
621 for (Index = 0; Index < UcCount; Index++) {
622 GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable, NULL, &RawMemoryRanges[Index]);
623 }
624
625 for (Index = UcCount; Index < UcCount + WtCount; Index++) {
626 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, NULL, &RawMemoryRanges[Index]);
627 }
628
629 for (Index = UcCount + WtCount; Index < UcCount + WtCount + WbCount; Index++) {
630 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, &RawMemoryRanges[Index]);
631 }
632
633 //
634 // 2. Generate WP MTRR and DO NOT overlap with WT, WB.
635 //
636 for (Index = UcCount + WtCount + WbCount; Index < UcCount + WtCount + WbCount + WpCount; Index++) {
637 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
638 while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount)) {
639 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
640 }
641 }
642
643 //
644 // 3. Generate WC MTRR and DO NOT overlap with WT, WB, WP.
645 //
646 for (Index = UcCount + WtCount + WbCount + WpCount; Index < UcCount + WtCount + WbCount + WpCount + WcCount; Index++) {
647 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
648 while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) {
649 GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
650 }
651 }
652}
653
657MTRR_MEMORY_CACHE_TYPE
659 VOID
660 )
661{
662 return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE (mMemoryCacheTypes) - 1)];
663}
664
679INT32
681 CONST VOID *Left,
682 CONST VOID *Right
683 )
684{
685 INT64 Delta;
686
687 Delta = (*(UINT64 *)Left - *(UINT64 *)Right);
688 if (Delta > 0) {
689 return 1;
690 } else if (Delta == 0) {
691 return 0;
692 } else {
693 return -1;
694 }
695}
696
705VOID
707 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
708 IN OUT MTRR_MEMORY_RANGE *Range,
709 IN MTRR_MEMORY_RANGE *Ranges,
710 IN UINT32 RangeCount
711 )
712{
713 UINT32 Index;
714
715 Range->Type = CacheInvalid;
716 for (Index = 0; Index < RangeCount; Index++) {
717 if (RangesOverlap (Range, &Ranges[Index], 1)) {
718 if (Ranges[Index].Type < Range->Type) {
719 Range->Type = Ranges[Index].Type;
720 }
721 }
722 }
723
724 if (Range->Type == CacheInvalid) {
725 Range->Type = DefaultType;
726 }
727}
728
738UINT32
740 IN UINT32 Index,
741 IN UINT64 *Array,
742 IN UINT32 Count
743 )
744{
745 UINT64 CurrentElement;
746
747 CurrentElement = Array[Index];
748 while ((Index < Count) && (CurrentElement == Array[Index])) {
749 Index++;
750 }
751
752 return Index;
753}
754
761VOID
763 IN OUT UINT64 *Array,
764 IN OUT UINT32 *Count
765 )
766{
767 UINT32 Index;
768 UINT32 NewCount;
769
770 Index = 0;
771 NewCount = 0;
772 while (Index < *Count) {
773 Array[NewCount] = Array[Index];
774 NewCount++;
775 Index = GetNextDifferentElementInSortedArray (Index, Array, *Count);
776 }
777
778 *Count = NewCount;
779}
780
788BOOLEAN
790 IN UINT64 Address,
792 )
793{
794 return (Address >= Range.BaseAddress) && (Address <= Range.BaseAddress + Range.Length - 1);
795}
796
804UINT64
806 IN MTRR_MEMORY_RANGE *RawMemoryRanges,
807 IN UINT32 RawMemoryRangeCount,
808 IN UINT64 Address
809 )
810{
811 UINT64 OverlapBitFlag;
812 UINT32 Index;
813
814 OverlapBitFlag = 0;
815 for (Index = 0; Index < RawMemoryRangeCount; Index++) {
816 if (AddressInRange (Address, RawMemoryRanges[Index])) {
817 OverlapBitFlag |= (1ull << Index);
818 }
819 }
820
821 return OverlapBitFlag;
822}
823
835UINT32
837 IN UINT64 Flag1,
838 IN UINT64 Flag2
839 )
840{
841 if (Flag1 == Flag2) {
842 return 0;
843 }
844
845 if ((Flag1 | Flag2) == Flag2) {
846 return 1;
847 }
848
849 if ((Flag1 | Flag2) == Flag1) {
850 return 2;
851 }
852
853 return 3;
854}
855
866BOOLEAN
868 IN UINT64 Endpoint,
869 IN MTRR_MEMORY_RANGE *Ranges,
870 IN UINTN RangeCount
871 )
872{
873 UINT32 Index;
874
875 for (Index = 0; Index < RangeCount; Index++) {
876 if (AddressInRange (Endpoint, Ranges[Index])) {
877 return TRUE;
878 }
879 }
880
881 return FALSE;
882}
883
892VOID
894 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
895 IN UINT32 PhysicalAddressBits,
896 IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges,
897 IN OUT UINTN *EffectiveMtrrMemoryRangesCount
898 )
899{
900 UINT64 MaxAddress;
901 UINTN NewRangesCountAtMost;
902 MTRR_MEMORY_RANGE *NewRanges;
903 UINTN NewRangesCountActual;
904 MTRR_MEMORY_RANGE *CurrentRangeInNewRanges;
905 MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges;
906
907 MTRR_MEMORY_RANGE *OldRanges;
908 MTRR_MEMORY_RANGE OldLastRange;
909 UINTN OldRangesIndex;
910
911 NewRangesCountActual = 0;
912 NewRangesCountAtMost = *EffectiveMtrrMemoryRangesCount + 2; // At most with 2 more range entries.
913 NewRanges = (MTRR_MEMORY_RANGE *)calloc (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE));
914 OldRanges = *EffectiveMtrrMemoryRanges;
915 if (OldRanges[0].BaseAddress > 0) {
916 NewRanges[NewRangesCountActual].BaseAddress = 0;
917 NewRanges[NewRangesCountActual].Length = OldRanges[0].BaseAddress;
918 NewRanges[NewRangesCountActual].Type = DefaultType;
919 NewRangesCountActual++;
920 }
921
922 OldRangesIndex = 0;
923 while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) {
924 CurrentRangeTypeInOldRanges = OldRanges[OldRangesIndex].Type;
925 CurrentRangeInNewRanges = NULL;
926 if (NewRangesCountActual > 0) {
927 // We need to check CurrentNewRange first before generate a new NewRange.
928 CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
929 }
930
931 if ((CurrentRangeInNewRanges != NULL) && (CurrentRangeInNewRanges->Type == CurrentRangeTypeInOldRanges)) {
932 CurrentRangeInNewRanges->Length += OldRanges[OldRangesIndex].Length;
933 } else {
934 NewRanges[NewRangesCountActual].BaseAddress = OldRanges[OldRangesIndex].BaseAddress;
935 NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
936 NewRanges[NewRangesCountActual].Type = CurrentRangeTypeInOldRanges;
937 while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && OldRanges[OldRangesIndex + 1].Type == CurrentRangeTypeInOldRanges) {
938 OldRangesIndex++;
939 NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
940 }
941
942 NewRangesCountActual++;
943 }
944
945 OldRangesIndex++;
946 }
947
948 MaxAddress = (1ull << PhysicalAddressBits) - 1;
949 OldLastRange = OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];
950 CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
951 if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) {
952 if (CurrentRangeInNewRanges->Type == DefaultType) {
953 CurrentRangeInNewRanges->Length = MaxAddress - CurrentRangeInNewRanges->BaseAddress + 1;
954 } else {
955 NewRanges[NewRangesCountActual].BaseAddress = OldLastRange.BaseAddress + OldLastRange.Length;
956 NewRanges[NewRangesCountActual].Length = MaxAddress - NewRanges[NewRangesCountActual].BaseAddress + 1;
957 NewRanges[NewRangesCountActual].Type = DefaultType;
958 NewRangesCountActual++;
959 }
960 }
961
962 free (*EffectiveMtrrMemoryRanges);
963 *EffectiveMtrrMemoryRanges = NewRanges;
964 *EffectiveMtrrMemoryRangesCount = NewRangesCountActual;
965}
966
975VOID
977 IN OUT UINT64 *Endpoints,
978 IN OUT UINT32 *EndPointCount,
979 IN MTRR_MEMORY_RANGE *RawMemoryRanges,
980 IN UINT32 RawMemoryRangeCount
981 )
982{
983 UINT32 Index;
984 UINT32 RawRangeIndex;
985
986 ASSERT ((RawMemoryRangeCount << 1) == *EndPointCount);
987
988 for (Index = 0; Index < *EndPointCount; Index += 2) {
989 RawRangeIndex = Index >> 1;
990 Endpoints[Index] = RawMemoryRanges[RawRangeIndex].BaseAddress;
991 Endpoints[Index + 1] = RawMemoryRanges[RawRangeIndex].BaseAddress + RawMemoryRanges[RawRangeIndex].Length - 1;
992 }
993
994 qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64);
995 RemoveDuplicatesInSortedArray (Endpoints, EndPointCount);
996}
997
1008VOID
1010 IN MTRR_MEMORY_CACHE_TYPE DefaultType,
1011 IN UINT32 PhysicalAddressBits,
1012 IN MTRR_MEMORY_RANGE *RawMemoryRanges,
1013 IN UINT32 RawMemoryRangeCount,
1014 OUT MTRR_MEMORY_RANGE *MemoryRanges,
1015 OUT UINTN *MemoryRangeCount
1016 )
1017{
1018 UINTN Index;
1019 UINT32 AllEndPointsCount;
1020 UINT64 *AllEndPointsInclusive;
1021 UINT32 AllRangePiecesCountMax;
1022 MTRR_MEMORY_RANGE *AllRangePieces;
1023 UINTN AllRangePiecesCountActual;
1024 UINT64 OverlapBitFlag1;
1025 UINT64 OverlapBitFlag2;
1026 INT32 OverlapFlagRelation;
1027
1028 if (RawMemoryRangeCount == 0) {
1029 MemoryRanges[0].BaseAddress = 0;
1030 MemoryRanges[0].Length = (1ull << PhysicalAddressBits);
1031 MemoryRanges[0].Type = DefaultType;
1032 *MemoryRangeCount = 1;
1033 return;
1034 }
1035
1036 AllEndPointsCount = RawMemoryRangeCount << 1;
1037 AllEndPointsInclusive = calloc (AllEndPointsCount, sizeof (UINT64));
1038 AllRangePiecesCountMax = RawMemoryRangeCount * 3 + 1;
1039 AllRangePieces = calloc (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE));
1040 CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemoryRanges, RawMemoryRangeCount);
1041
1042 for (Index = 0, AllRangePiecesCountActual = 0; Index < AllEndPointsCount - 1; Index++) {
1043 OverlapBitFlag1 = GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index]);
1044 OverlapBitFlag2 = GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index + 1]);
1045 OverlapFlagRelation = CheckOverlapBitFlagsRelation (OverlapBitFlag1, OverlapBitFlag2);
1046 switch (OverlapFlagRelation) {
1047 case 0: // [1, 2]
1048 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1049 AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1;
1050 AllRangePiecesCountActual++;
1051 break;
1052 case 1: // [1, 2)
1053 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1054 AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1;
1055 AllRangePiecesCountActual++;
1056 break;
1057 case 2: // (1, 2]
1058 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
1059 AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1;
1060 AllRangePiecesCountActual++;
1061
1062 if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
1063 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1064 AllRangePieces[AllRangePiecesCountActual].Length = 1;
1065 AllRangePiecesCountActual++;
1066 }
1067
1068 break;
1069 case 3: // (1, 2)
1070 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
1071 AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + 1) + 1;
1072 if (AllRangePieces[AllRangePiecesCountActual].Length == 0) {
1073 // Only in case 3 can exists Length=0, we should skip such "segment".
1074 break;
1075 }
1076
1077 AllRangePiecesCountActual++;
1078 if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
1079 AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
1080 AllRangePieces[AllRangePiecesCountActual].Length = 1;
1081 AllRangePiecesCountActual++;
1082 }
1083
1084 break;
1085 default:
1086 ASSERT (FALSE);
1087 }
1088 }
1089
1090 for (Index = 0; Index < AllRangePiecesCountActual; Index++) {
1091 DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index], RawMemoryRanges, RawMemoryRangeCount);
1092 }
1093
1094 CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAddressBits, &AllRangePieces, &AllRangePiecesCountActual);
1095 ASSERT (*MemoryRangeCount >= AllRangePiecesCountActual);
1096 memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * sizeof (MTRR_MEMORY_RANGE));
1097 *MemoryRangeCount = AllRangePiecesCountActual;
1098
1099 free (AllEndPointsInclusive);
1100 free (AllRangePieces);
1101}
UINT64 UINTN
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MSR_IA32_MTRR_PHYSBASE0
#define MSR_IA32_MTRR_DEF_TYPE
#define MSR_IA32_MTRRCAP
#define MSR_IA32_MTRR_PHYSMASK0
#define MSR_IA32_TME_ACTIVATE
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
Definition: Cpuid.h:1301
#define CPUID_SIGNATURE
Definition: Cpuid.h:45
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
UINT64 Random64(UINT64 Start, UINT64 Limit)
Definition: Support.c:497
VOID CollectTestResult(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN UINT32 VariableMtrrCount, IN MTRR_SETTINGS *Mtrrs, OUT MTRR_MEMORY_RANGE *Ranges, IN OUT UINTN *RangeCount, OUT UINT32 *MtrrCount)
Definition: Support.c:437
UINT32 GetNextDifferentElementInSortedArray(IN UINT32 Index, IN UINT64 *Array, IN UINT32 Count)
Definition: Support.c:739
BOOLEAN IsEndpointInRanges(IN UINT64 Endpoint, IN MTRR_MEMORY_RANGE *Ranges, IN UINTN RangeCount)
Definition: Support.c:867
UINT64 EFIAPI UnitTestMtrrLibAsmReadMsr64(IN UINT32 MsrIndex)
Definition: Support.c:232
VOID RemoveDuplicatesInSortedArray(IN OUT UINT64 *Array, IN OUT UINT32 *Count)
Definition: Support.c:762
VOID GenerateValidAndConfigurableMtrrPairs(IN UINT32 PhysicalAddressBits, IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 UcCount, IN UINT32 WtCount, IN UINT32 WbCount, IN UINT32 WpCount, IN UINT32 WcCount)
Definition: Support.c:606
UINT64 GetOverlapBitFlag(IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount, IN UINT64 Address)
Definition: Support.c:805
VOID CollectEndpoints(IN OUT UINT64 *Endpoints, IN OUT UINT32 *EndPointCount, IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount)
Definition: Support.c:976
VOID GenerateRandomNumbers(CHAR8 *FilePath, UINTN Count)
Definition: Support.c:68
UINT64 EFIAPI UnitTestMtrrLibAsmWriteMsr64(IN UINT32 MsrIndex, IN UINT64 Value)
Definition: Support.c:298
UNIT_TEST_STATUS EFIAPI InitializeMtrrRegs(IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter)
Definition: Support.c:358
UINT32 Random32(UINT32 Start, UINT32 Limit)
Definition: Support.c:481
UINT32 CheckOverlapBitFlagsRelation(IN UINT64 Flag1, IN UINT64 Flag2)
Definition: Support.c:836
MTRR_MEMORY_CACHE_TYPE GenerateRandomCacheType(VOID)
Definition: Support.c:658
INT32 CompareFuncUint64(CONST VOID *Left, CONST VOID *Right)
Definition: Support.c:680
BOOLEAN RangesOverlap(IN MTRR_MEMORY_RANGE *Range, IN MTRR_MEMORY_RANGE *Ranges, IN UINTN Count)
Definition: Support.c:572
UINT32 EFIAPI UnitTestMtrrLibAsmCpuid(IN UINT32 Index, OUT UINT32 *Eax OPTIONAL, OUT UINT32 *Ebx OPTIONAL, OUT UINT32 *Ecx OPTIONAL, OUT UINT32 *Edx OPTIONAL)
Definition: Support.c:205
UINTN Rand(VOID)
Definition: Support.c:39
UINT32 EFIAPI UnitTestMtrrLibAsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *Eax OPTIONAL, OUT UINT32 *Ebx OPTIONAL, OUT UINT32 *Ecx OPTIONAL, OUT UINT32 *Edx OPTIONAL)
Definition: Support.c:124
UNIT_TEST_STATUS EFIAPI InitializeSystem(IN UNIT_TEST_CONTEXT Context)
Definition: Support.c:418
BOOLEAN AddressInRange(IN UINT64 Address, IN MTRR_MEMORY_RANGE Range)
Definition: Support.c:789
VOID CompactAndExtendEffectiveMtrrMemoryRanges(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges, IN OUT UINTN *EffectiveMtrrMemoryRangesCount)
Definition: Support.c:893
VOID GetEffectiveMemoryRanges(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN UINT32 PhysicalAddressBits, IN MTRR_MEMORY_RANGE *RawMemoryRanges, IN UINT32 RawMemoryRangeCount, OUT MTRR_MEMORY_RANGE *MemoryRanges, OUT UINTN *MemoryRangeCount)
Definition: Support.c:1009
VOID GenerateRandomMtrrPair(IN UINT32 PhysicalAddressBits, IN MTRR_MEMORY_CACHE_TYPE CacheType, OUT MTRR_VARIABLE_SETTING *MtrrPair OPTIONAL, OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL)
Definition: Support.c:514
VOID DetermineMemoryCacheType(IN MTRR_MEMORY_CACHE_TYPE DefaultType, IN OUT MTRR_MEMORY_RANGE *Range, IN MTRR_MEMORY_RANGE *Ranges, IN UINT32 RangeCount)
Definition: Support.c:706
VOID * UNIT_TEST_CONTEXT
Definition: UnitTestLib.h:54
#define UT_ASSERT_TRUE(Expression)
Definition: UnitTestLib.h:350
#define UT_ASSERT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:375
UINT32 UNIT_TEST_STATUS
Definition: UnitTestLib.h:16
UNIT_TEST_HOST_BASE_LIB gUnitTestHostBaseLib
struct CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX::@709 Bits
struct CPUID_VERSION_INFO_EDX::@696 Bits
struct CPUID_VIR_PHY_ADDRESS_SIZE_EAX::@753 Bits
struct MSR_IA32_MTRR_DEF_TYPE_REGISTER::@653 Bits
struct MSR_IA32_MTRR_PHYSBASE_REGISTER::@649 Bits
struct MSR_IA32_MTRR_PHYSMASK_REGISTER::@650 Bits
struct MSR_IA32_MTRRCAP_REGISTER::@631 Bits
struct MSR_IA32_TME_ACTIVATE_REGISTER::@680 Bits