TianoCore EDK2 master
Loading...
Searching...
No Matches
RandomTest.c
Go to the documentation of this file.
1
10#include "RandomTest.h"
11
12UINTN RandomNumber = 0;
13extern IA32_PAGING_ENTRY mValidMaskNoLeaf[6];
14extern IA32_PAGING_ENTRY mValidMaskLeaf[6];
15extern IA32_PAGING_ENTRY mValidMaskLeafFlag[6];
16UINTN mRandomOption;
17IA32_MAP_ATTRIBUTE mSupportedBit;
18extern UINTN mNumberCount;
19extern UINT8 mNumbers[];
20UINTN mNumberIndex;
21UINT64 AlignedTable[] = {
22 ~((UINT64)SIZE_4KB - 1),
23 ~((UINT64)SIZE_2MB - 1),
24 ~((UINT64)SIZE_1GB - 1)
25};
26
38BOOLEAN
39EFIAPI
41 OUT UINT8 *Output,
42 IN UINTN Size
43 )
44{
45 UINTN Index;
46
47 for (Index = 0; Index < Size; Index++) {
48 if (mNumberIndex >= mNumberCount) {
49 mNumberIndex = 0;
50 }
51
52 Output[Index] = mNumbers[mNumberIndex];
53 mNumberIndex++;
54 }
55
56 return TRUE;
57}
58
70BOOLEAN
71EFIAPI
73 OUT UINT8 *Output,
74 IN UINTN Size
75 )
76{
77 if (mRandomOption & USE_RANDOM_ARRAY) {
78 return RandomBytesUsingArray (Output, Size);
79 } else {
80 return RandomBytes (Output, Size);
81 }
82}
83
91UINT32
93 UINT32 Start,
94 UINT32 Limit
95 )
96{
97 UINT64 Value;
98
99 LocalRandomBytes ((UINT8 *)&Value, sizeof (UINT64));
100 return (UINT32)(Value % (Limit - Start + 1)) + Start;
101}
102
110UINT64
112 UINT64 Start,
113 UINT64 Limit
114 )
115{
116 UINT64 Value;
117
118 LocalRandomBytes ((UINT8 *)&Value, sizeof (UINT64));
119 if (Limit - Start == MAX_UINT64) {
120 return (UINT64)(Value);
121 }
122
123 return (UINT64)(Value % (Limit - Start + 1)) + Start;
124}
125
133BOOLEAN
135 UINT8 Probability
136 )
137{
138 return ((Probability > ((UINT8)Random64 (0, 100))) ? TRUE : FALSE);
139}
140
144VOID
146 VOID
147 )
148{
149 UINT64 Buffer[SIZE_1KB];
150 UINTN Index;
151
152 for (Index = 0; Index < SIZE_1KB; Index++) {
153 Buffer[Index] = Random64 (0, MAX_UINT64);
154 Buffer[Index] = Buffer[Index];
155 }
156}
157
170 IN IA32_PAGING_ENTRY *PagingEntry,
171 IN UINTN Level,
172 IN UINTN MaxLeafLevel,
173 IN UINT64 Address
174 )
175{
176 UINT64 Index;
177 UINT32 PageTableBaseAddressLow;
178 UINT32 PageTableBaseAddressHigh;
179 IA32_PAGING_ENTRY *ChildPageEntry;
180 UNIT_TEST_STATUS Status;
181
182 if (PagingEntry->Pce.Present == 0) {
183 return UNIT_TEST_PASSED;
184 }
185
186 if ((PagingEntry->Uint64 & mValidMaskLeafFlag[Level].Uint64) == mValidMaskLeafFlag[Level].Uint64) {
187 //
188 // It is a Leaf
189 //
190 if (Level > MaxLeafLevel) {
191 UT_ASSERT_TRUE (Level <= MaxLeafLevel);
192 }
193
194 if ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64) != PagingEntry->Uint64) {
195 UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64), PagingEntry->Uint64);
196 }
197
198 if ((RandomNumber < 100) && RandomBoolean (50)) {
199 RandomNumber++;
200 if (Level == 1) {
201 PageTableBaseAddressLow = PagingEntry->Pte4K.Bits.PageTableBaseAddressLow;
202 PageTableBaseAddressHigh = PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh;
203 } else {
204 PageTableBaseAddressLow = PagingEntry->PleB.Bits.PageTableBaseAddressLow;
205 PageTableBaseAddressHigh = PagingEntry->PleB.Bits.PageTableBaseAddressHigh;
206 }
207
208 PagingEntry->Uint64 = (Random64 (0, MAX_UINT64) & mValidMaskLeaf[Level].Uint64) | mValidMaskLeafFlag[Level].Uint64;
209 PagingEntry->Pte4K.Bits.Present = 1;
210 if (Level == 1) {
211 PagingEntry->Pte4K.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow;
212 PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh;
213 } else {
214 PagingEntry->PleB.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow;
215 PagingEntry->PleB.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh;
216 }
217
218 if ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64) != PagingEntry->Uint64) {
219 UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64), PagingEntry->Uint64);
220 }
221 }
222
223 return UNIT_TEST_PASSED;
224 }
225
226 //
227 // Not a leaf
228 //
229 UT_ASSERT_NOT_EQUAL (Level, 1);
230 if ((PagingEntry->Uint64 & mValidMaskNoLeaf[Level].Uint64) != PagingEntry->Uint64) {
231 DEBUG ((DEBUG_ERROR, "ERROR: Level %d no Leaf entry is 0x%lx, which reserved bit is set \n", Level, PagingEntry->Uint64));
232 UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskNoLeaf[Level].Uint64), PagingEntry->Uint64);
233 }
234
235 if ((RandomNumber < 100) && RandomBoolean (50)) {
236 RandomNumber++;
237 PageTableBaseAddressLow = PagingEntry->PleB.Bits.PageTableBaseAddressLow;
238 PageTableBaseAddressHigh = PagingEntry->PleB.Bits.PageTableBaseAddressHigh;
239
240 PagingEntry->Uint64 = Random64 (0, MAX_UINT64) & mValidMaskNoLeaf[Level].Uint64;
241 PagingEntry->Pnle.Bits.Present = 1;
242 PagingEntry->PleB.Bits.PageTableBaseAddressLow = PageTableBaseAddressLow;
243 PagingEntry->PleB.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh;
244 ASSERT ((PagingEntry->Uint64 & mValidMaskLeafFlag[Level].Uint64) != mValidMaskLeafFlag[Level].Uint64);
245 }
246
247 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle));
248 for (Index = 0; Index < 512; Index++) {
249 Status = ValidateAndRandomeModifyPageTablePageTableEntry (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3)));
250 if (Status != UNIT_TEST_PASSED) {
251 return Status;
252 }
253 }
254
255 return UNIT_TEST_PASSED;
256}
257
268 IN UINTN PageTable,
269 IN PAGING_MODE PagingMode
270 )
271{
272 UINTN MaxLevel;
273 UINTN MaxLeafLevel;
274 UINT64 Index;
275 UNIT_TEST_STATUS Status;
276 IA32_PAGING_ENTRY *PagingEntry;
277
278 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
279 //
280 // 32bit paging is never supported.
281 //
282 return UNIT_TEST_ERROR_TEST_FAILED;
283 }
284
285 MaxLeafLevel = (UINT8)PagingMode;
286 MaxLevel = (UINT8)(PagingMode >> 8);
287
288 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable;
289 for (Index = 0; Index < 512; Index++) {
290 Status = ValidateAndRandomeModifyPageTablePageTableEntry (&PagingEntry[Index], MaxLevel, MaxLeafLevel, Index << (9 * MaxLevel + 3));
291 if (Status != UNIT_TEST_PASSED) {
292 return Status;
293 }
294 }
295
296 return Status;
297}
298
304VOID
306 IN OUT MAP_ENTRYS *MapEntrys
307 )
308{
309 UINTN MapsIndex;
310
311 if (MapEntrys->Count == 0) {
312 return;
313 }
314
315 MapsIndex = MapEntrys->Count - 1;
316 ZeroMem (&(MapEntrys->Maps[MapsIndex]), sizeof (MAP_ENTRY));
317 MapEntrys->Count = MapsIndex;
318}
319
328VOID
330 IN UINT64 MaxAddress,
331 IN OUT MAP_ENTRYS *MapEntrys
332 )
333{
334 UINTN MapsIndex;
335 UINT64 FormerLinearAddress;
336 UINT64 FormerLinearAddressBottom;
337 UINT64 FormerLinearAddressTop;
338
339 MapsIndex = MapEntrys->Count;
340
341 ASSERT (MapsIndex < MapEntrys->MaxCount);
342 //
343 // use AlignedTable to avoid that a random number can be very hard to be 1G or 2M aligned
344 //
345 if ((MapsIndex != 0) && (RandomBoolean (50))) {
346 FormerLinearAddress = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].LinearAddress;
347 if (FormerLinearAddress < 2 * (UINT64)SIZE_1GB) {
348 FormerLinearAddressBottom = 0;
349 } else {
350 FormerLinearAddressBottom = FormerLinearAddress - 2 * (UINT64)SIZE_1GB;
351 }
352
353 if (FormerLinearAddress + 2 * (UINT64)SIZE_1GB > MaxAddress) {
354 FormerLinearAddressTop = MaxAddress;
355 } else {
356 FormerLinearAddressTop = FormerLinearAddress + 2 * (UINT64)SIZE_1GB;
357 }
358
359 MapEntrys->Maps[MapsIndex].LinearAddress = Random64 (FormerLinearAddressBottom, FormerLinearAddressTop) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)];
360 } else {
361 MapEntrys->Maps[MapsIndex].LinearAddress = Random64 (0, MaxAddress) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)];
362 }
363
364 //
365 // To have better performance, limit the size less than 10G
366 //
367 MapEntrys->Maps[MapsIndex].Length = Random64 (0, MIN (MaxAddress - MapEntrys->Maps[MapsIndex].LinearAddress, 10 * (UINT64)SIZE_1GB)) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)];
368
369 if ((MapsIndex != 0) && (RandomBoolean (50))) {
370 MapEntrys->Maps[MapsIndex].Attribute.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Attribute.Uint64;
371 MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64;
372 } else {
373 MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
374 if (RandomBoolean (5)) {
375 //
376 // The probability to get random Mask should be small since all bits of a random number
377 // have a high probability of containing 0, which may be a invalid input.
378 //
379 MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
380 } else {
381 MapEntrys->Maps[MapsIndex].Mask.Uint64 = MAX_UINT64;
382 }
383
384 if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) {
385 MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF;
386 }
387 }
388
389 if (mRandomOption & ONLY_ONE_ONE_MAPPING) {
390 MapEntrys->Maps[MapsIndex].Attribute.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK);
391 MapEntrys->Maps[MapsIndex].Attribute.Uint64 |= MapEntrys->Maps[MapsIndex].LinearAddress;
392 MapEntrys->Maps[MapsIndex].Mask.Uint64 |= IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK;
393 } else {
394 MapEntrys->Maps[MapsIndex].Attribute.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK);
395 MapEntrys->Maps[MapsIndex].Attribute.Uint64 |= (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)]);
396 }
397
398 MapEntrys->Count += 1;
399}
400
417BOOLEAN
419 IN UINT64 Address,
420 IN MAP_ENTRYS *MapEntrys,
421 IN IA32_MAP_ENTRY *Map,
422 IN UINTN MapCount,
423 IN IA32_MAP_ENTRY *InitMap,
424 IN UINTN InitMapCount
425 )
426{
427 UINTN Index;
428 IA32_MAP_ATTRIBUTE AttributeInInitMap;
429 IA32_MAP_ATTRIBUTE AttributeInMap;
430 IA32_MAP_ATTRIBUTE AttributeInMapEntrys;
431 IA32_MAP_ATTRIBUTE MaskInMapEntrys;
432
433 AttributeInMap.Uint64 = 0;
434 AttributeInMapEntrys.Uint64 = 0;
435 AttributeInInitMap.Uint64 = 0;
436 MaskInMapEntrys.Uint64 = 0;
437 //
438 // Assume every entry in maps does not overlap with each other
439 //
440 for (Index = 0; Index < MapCount; Index++) {
441 if ((Address >= Map[Index].LinearAddress) && (Address < (Map[Index].LinearAddress + Map[Index].Length))) {
442 AttributeInMap.Uint64 = (Map[Index].Attribute.Uint64 & mSupportedBit.Uint64);
443 AttributeInMap.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK);
444 AttributeInMap.Uint64 |= (Address - Map[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&Map[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK;
445 break;
446 }
447 }
448
449 //
450 // Assume every entry in maps does not overlap with each other
451 //
452 for (Index = 0; Index < InitMapCount; Index++) {
453 if ((Address >= InitMap[Index].LinearAddress) && (Address < (InitMap[Index].LinearAddress + InitMap[Index].Length))) {
454 AttributeInInitMap.Uint64 = (InitMap[Index].Attribute.Uint64 & mSupportedBit.Uint64);
455 AttributeInInitMap.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK);
456 AttributeInInitMap.Uint64 |= (Address - InitMap[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&InitMap[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK;
457
458 break;
459 }
460 }
461
462 AttributeInMapEntrys.Uint64 = AttributeInInitMap.Uint64;
463
464 for (Index = MapEntrys->InitCount; Index < MapEntrys->Count; Index++) {
465 if ((Address >= MapEntrys->Maps[Index].LinearAddress) && (Address < (MapEntrys->Maps[Index].LinearAddress + MapEntrys->Maps[Index].Length))) {
466 if (AttributeInMapEntrys.Bits.Present == 0) {
467 AttributeInMapEntrys.Uint64 = 0;
468 MaskInMapEntrys.Uint64 = 0;
469 }
470
471 MaskInMapEntrys.Uint64 |= MapEntrys->Maps[Index].Mask.Uint64;
472 AttributeInMapEntrys.Uint64 &= (~MapEntrys->Maps[Index].Mask.Uint64);
473 AttributeInMapEntrys.Uint64 |= (MapEntrys->Maps[Index].Attribute.Uint64 & MapEntrys->Maps[Index].Mask.Uint64);
474 if (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&MapEntrys->Maps[Index].Mask) != 0) {
475 AttributeInMapEntrys.Uint64 &= (~IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK);
476 AttributeInMapEntrys.Uint64 |= (Address - MapEntrys->Maps[Index].LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&MapEntrys->Maps[Index].Attribute)) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK;
477 }
478 }
479 }
480
481 if (AttributeInMap.Bits.Present == 0) {
482 if (AttributeInMapEntrys.Bits.Present == 0) {
483 return TRUE;
484 }
485 }
486
487 if ((AttributeInMap.Uint64 & MaskInMapEntrys.Uint64) != (AttributeInMapEntrys.Uint64 & MaskInMapEntrys.Uint64)) {
488 DEBUG ((DEBUG_INFO, "======detailed information begin=====\n"));
489 DEBUG ((DEBUG_INFO, "\nError: Detect different attribute on a point with linear address: 0x%lx\n", Address));
490 DEBUG ((DEBUG_INFO, "By parsing page table, the point has Attribute 0x%lx, and map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMap) & MaskInMapEntrys.Uint64, IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&AttributeInMap)));
491 DEBUG ((DEBUG_INFO, "While according to inputs, the point should Attribute 0x%lx, and should map to physical address 0x%lx\n", IA32_MAP_ATTRIBUTE_ATTRIBUTES (&AttributeInMapEntrys) & MaskInMapEntrys.Uint64, IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&AttributeInMapEntrys)));
492 DEBUG ((DEBUG_INFO, "The total Mask is 0x%lx\n", MaskInMapEntrys.Uint64));
493
494 if (MapEntrys->InitCount != 0) {
495 DEBUG ((DEBUG_INFO, "Below is the initialization status:\n"));
496 for (Index = 0; Index < InitMapCount; Index++) {
497 if ((Address >= InitMap[Index].LinearAddress) && (Address < (InitMap[Index].LinearAddress + InitMap[Index].Length))) {
498 DEBUG ((DEBUG_INFO, " *"));
499 } else {
500 DEBUG ((DEBUG_INFO, " "));
501 }
502
503 DEBUG ((DEBUG_INFO, " %02d: {0x%lx, 0x%lx, 0x%lx}\n", Index, InitMap[Index].LinearAddress, InitMap[Index].LinearAddress + InitMap[Index].Length, InitMap[Index].Attribute.Uint64));
504 }
505 }
506
507 DEBUG ((DEBUG_INFO, "Below is the inputs:\n"));
508 DEBUG ((DEBUG_INFO, " Index: {LinearAddress, LinearLimit, Mask, Attribute}\n"));
509 for (Index = MapEntrys->InitCount; Index < MapEntrys->Count; Index++) {
510 if ((Address >= MapEntrys->Maps[Index].LinearAddress) && (Address < (MapEntrys->Maps[Index].LinearAddress + MapEntrys->Maps[Index].Length))) {
511 DEBUG ((DEBUG_INFO, " *"));
512 } else {
513 DEBUG ((DEBUG_INFO, " "));
514 }
515
516 DEBUG ((
517 DEBUG_INFO,
518 " %02d: {0x%lx, 0x%lx, 0x%lx,0x%lx}\n",
519 Index,
520 MapEntrys->Maps[Index].LinearAddress,
521 MapEntrys->Maps[Index].LinearAddress + MapEntrys->Maps[Index].Length,
522 MapEntrys->Maps[Index].Mask.Uint64,
523 MapEntrys->Maps[Index].Attribute.Uint64
524 ));
525 }
526
527 DEBUG ((DEBUG_INFO, "Below is the dumped from pagetable:\n"));
528 for (Index = 0; Index < MapCount; Index++) {
529 if ((Address >= Map[Index].LinearAddress) && (Address < (Map[Index].LinearAddress + Map[Index].Length))) {
530 DEBUG ((DEBUG_INFO, " *"));
531 } else {
532 DEBUG ((DEBUG_INFO, " "));
533 }
534
535 DEBUG ((DEBUG_INFO, "%02d: {0x%lx, 0x%lx, 0x%lx}\n", Index, Map[Index].LinearAddress, Map[Index].LinearAddress + Map[Index].Length, Map[Index].Attribute.Uint64));
536 }
537
538 DEBUG ((DEBUG_INFO, "======detailed information done=====\n"));
539 return FALSE;
540 }
541
542 return TRUE;
543}
544
553VOID
555 IN OUT UINT64 *Buffer,
556 IN OUT UINTN *Count,
557 IN UINT64 Address
558 )
559{
560 if ( Buffer != NULL) {
561 Buffer[*Count] = Address;
562 (*Count)++;
563 Buffer[*Count] = Address+1;
564 (*Count)++;
565 Buffer[*Count] = Address-1;
566 (*Count)++;
567 } else {
568 (*Count) = (*Count) +3;
569 }
570}
571
582VOID
584 IN MAP_ENTRYS *MapEntrys,
585 IN IA32_MAP_ENTRY *Map,
586 IN UINTN MapCount,
587 IN OUT UINT64 *Buffer,
588 IN OUT UINTN *Count
589 )
590{
591 UINTN TemCount;
592 UINTN Index1;
593 UINTN Index2;
594
595 TemCount = 0;
596
597 for (Index1 = 0; Index1 < MapEntrys->Count; Index1++) {
598 AppendKeyPointToBuffer (Buffer, &TemCount, MapEntrys->Maps[Index1].LinearAddress);
599 AppendKeyPointToBuffer (Buffer, &TemCount, MapEntrys->Maps[Index1].LinearAddress + MapEntrys->Maps[Index1].Length);
600 }
601
602 for (Index2 = 0; Index2 < MapCount; Index2++) {
603 if (Buffer != NULL) {
604 for (Index1 = 0; Index1 < TemCount; Index1++) {
605 if (Buffer[Index1] == Map[Index2].LinearAddress) {
606 break;
607 }
608 }
609
610 if (Index1 < TemCount) {
611 continue;
612 }
613 }
614
615 AppendKeyPointToBuffer (Buffer, &TemCount, Map[Index2].LinearAddress);
616 }
617
618 for (Index2 = 0; Index2 < MapCount; Index2++) {
619 if (Buffer != NULL) {
620 for (Index1 = 0; Index1 < TemCount; Index1++) {
621 if (Buffer[Index1] == (Map[Index2].LinearAddress + Map[Index2].Length)) {
622 break;
623 }
624 }
625
626 if (Index1 < TemCount) {
627 continue;
628 }
629 }
630
631 AppendKeyPointToBuffer (Buffer, &TemCount, Map[Index2].LinearAddress + Map[Index2].Length);
632 }
633
634 *Count = TemCount;
635}
636
653 IN OUT UINTN *PageTable,
654 IN PAGING_MODE PagingMode,
655 IN UINT64 MaxAddress,
656 IN MAP_ENTRYS *MapEntrys,
657 IN ALLOCATE_PAGE_RECORDS *PagesRecord,
658 IN IA32_MAP_ENTRY *InitMap,
659 IN UINTN InitMapCount
660 )
661{
662 UINTN MapsIndex;
663 RETURN_STATUS Status;
664 UINTN PageTableBufferSize;
665 VOID *Buffer;
666 IA32_MAP_ENTRY *Map;
667 UINTN MapCount;
668 IA32_MAP_ENTRY *Map2;
669 UINTN MapCount2;
670 UINTN Index;
671 UINTN KeyPointCount;
672 UINTN NewKeyPointCount;
673 UINT64 *KeyPointBuffer;
674 UINTN Level;
675 UINT64 Value;
676 UNIT_TEST_STATUS TestStatus;
677 MAP_ENTRY *LastMapEntry;
678 IA32_MAP_ATTRIBUTE *Mask;
679 IA32_MAP_ATTRIBUTE *Attribute;
680 UINT64 LastNotPresentRegionStart;
681 BOOLEAN IsNotPresent;
682 BOOLEAN IsModified;
683
684 MapsIndex = MapEntrys->Count;
685 MapCount = 0;
686 LastNotPresentRegionStart = 0;
687 IsNotPresent = FALSE;
688 IsModified = FALSE;
689
691 GenerateSingleRandomMapEntry (MaxAddress, MapEntrys);
692 LastMapEntry = &MapEntrys->Maps[MapsIndex];
693 Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount);
694
695 if (MapCount != 0) {
697 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY)));
698 ASSERT (Map != NULL);
699 Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount);
700 }
701
702 //
703 // Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range.
704 //
705 if (LastMapEntry->Length > 0) {
706 for (Index = 0; Index < MapCount; Index++) {
707 if ((LastNotPresentRegionStart < Map[Index].LinearAddress) &&
708 (LastMapEntry->LinearAddress < Map[Index].LinearAddress) && (LastMapEntry->LinearAddress + LastMapEntry->Length > LastNotPresentRegionStart))
709 {
710 //
711 // MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table.
712 //
713 break;
714 }
715
716 LastNotPresentRegionStart = Map[Index].LinearAddress + Map[Index].Length;
717 }
718
719 //
720 // Either LastMapEntry overlaps with the not-present region in the very end
721 // Or it overlaps with one in the middle
722 if (LastNotPresentRegionStart < LastMapEntry->LinearAddress + LastMapEntry->Length) {
723 IsNotPresent = TRUE;
724 }
725 }
726
727 PageTableBufferSize = 0;
728 Status = PageTableMap (
729 PageTable,
730 PagingMode,
731 NULL,
732 &PageTableBufferSize,
733 LastMapEntry->LinearAddress,
734 LastMapEntry->Length,
735 &LastMapEntry->Attribute,
736 &LastMapEntry->Mask,
737 &IsModified
738 );
739
740 Attribute = &LastMapEntry->Attribute;
741 Mask = &LastMapEntry->Mask;
742 //
743 // If set [LinearAddress, LinearAddress+Attribute] to not preset, all
744 // other attributes should not be provided.
745 //
746 if ((LastMapEntry->Length > 0) && (Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) {
747 RemoveLastMapEntry (MapEntrys);
749 return UNIT_TEST_PASSED;
750 }
751
752 //
753 // Return Status for non-present range also should be InvalidParameter when:
754 // 1. Some of attributes are not provided when mapping non-present range to present.
755 // 2. Set any other attribute without setting the non-present range to Present.
756 //
757 if (IsNotPresent) {
758 if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {
759 //
760 // Creating new page table or remapping non-present range to present.
761 //
762 if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) ||
763 (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) ||
764 ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0))
765 {
766 RemoveLastMapEntry (MapEntrys);
768 return UNIT_TEST_PASSED;
769 }
770 } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) {
771 //
772 // Only change other attributes for non-present range is not permitted.
773 //
774 RemoveLastMapEntry (MapEntrys);
776 return UNIT_TEST_PASSED;
777 }
778 }
779
780 if (PageTableBufferSize != 0) {
782
783 //
784 // Allocate memory for Page table
785 // Note the memory is used in one complete Random test.
786 //
787 Buffer = PagesRecord->AllocatePagesForPageTable (PagesRecord, EFI_SIZE_TO_PAGES (PageTableBufferSize));
788 UT_ASSERT_NOT_EQUAL (Buffer, NULL);
789 Status = PageTableMap (
790 PageTable,
791 PagingMode,
792 Buffer,
793 &PageTableBufferSize,
794 LastMapEntry->LinearAddress,
795 LastMapEntry->Length,
796 &LastMapEntry->Attribute,
797 &LastMapEntry->Mask,
798 &IsModified
799 );
800 }
801
802 if (Status != RETURN_SUCCESS ) {
804 }
805
807 TestStatus = IsPageTableValid (*PageTable, PagingMode);
808 if (TestStatus != UNIT_TEST_PASSED) {
809 return TestStatus;
810 }
811
812 MapCount2 = 0;
813 Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount2);
814 if (MapCount2 != 0) {
816
817 //
818 // Allocate memory for Map2
819 // Note the memory is only used in this one Single MapEntry Test
820 //
821 Map2 = AllocatePages (EFI_SIZE_TO_PAGES (MapCount2 * sizeof (IA32_MAP_ENTRY)));
822 ASSERT (Map2 != NULL);
823 Status = PageTableParse (*PageTable, PagingMode, Map2, &MapCount2);
824 }
825
826 //
827 // Check if PageTable has been modified.
828 //
829 if (MapCount2 != MapCount) {
830 UT_ASSERT_EQUAL (IsModified, TRUE);
831 } else {
832 if (CompareMem (Map, Map2, MapCount2 * sizeof (IA32_MAP_ENTRY)) != 0) {
833 UT_ASSERT_EQUAL (IsModified, TRUE);
834 } else {
835 UT_ASSERT_EQUAL (IsModified, FALSE);
836 }
837 }
838
840
841 //
842 // Allocate memory to record all key point
843 // Note the memory is only used in this one Single MapEntry Test
844 //
845 KeyPointCount = 0;
846 GetKeyPointList (MapEntrys, Map2, MapCount2, NULL, &KeyPointCount);
847 KeyPointBuffer = AllocatePages (EFI_SIZE_TO_PAGES (KeyPointCount * sizeof (UINT64)));
848 ASSERT (KeyPointBuffer != NULL);
849 NewKeyPointCount = 0;
850 GetKeyPointList (MapEntrys, Map2, MapCount2, KeyPointBuffer, &NewKeyPointCount);
851
852 //
853 // Compare all key point's attribute
854 //
855 for (Index = 0; Index < NewKeyPointCount; Index++) {
856 if (!CompareEntrysforOnePoint (KeyPointBuffer[Index], MapEntrys, Map2, MapCount2, InitMap, InitMapCount)) {
857 DEBUG ((DEBUG_INFO, "Error happens at below key point\n"));
858 DEBUG ((DEBUG_INFO, "Index = %d KeyPointBuffer[Index] = 0x%lx\n", Index, KeyPointBuffer[Index]));
859 Value = GetEntryFromPageTable (*PageTable, PagingMode, KeyPointBuffer[Index], &Level);
860 DEBUG ((DEBUG_INFO, "From Page table, this key point is in level %d entry, with entry value is 0x%lx\n", Level, Value));
862 }
863 }
864
865 FreePages (KeyPointBuffer, EFI_SIZE_TO_PAGES (KeyPointCount * sizeof (UINT64)));
866 if (MapCount != 0) {
867 FreePages (Map, EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY)));
868 }
869
870 if (MapCount2 != 0) {
871 FreePages (Map2, EFI_SIZE_TO_PAGES (MapCount2 * sizeof (IA32_MAP_ENTRY)));
872 }
873
874 return UNIT_TEST_PASSED;
875}
876
885VOID *
886EFIAPI
888 IN ALLOCATE_PAGE_RECORDS *PagesRecord,
889 IN UINTN Pages
890 )
891{
892 VOID *Buffer;
893
894 Buffer = NULL;
895 if (PagesRecord->Count < PagesRecord->MaxCount) {
896 Buffer = AllocatePages (Pages);
897 PagesRecord->Records[PagesRecord->Count].Buffer = Buffer;
898 PagesRecord->Records[PagesRecord->Count].Pages = Pages;
899 PagesRecord->Count++;
900 }
901
902 ASSERT (Buffer != NULL);
903
904 return Buffer;
905}
906
917 IN UINTN ExpctedEntryNumber,
918 IN PAGING_MODE PagingMode
919 )
920{
921 UINTN PageTable;
922 UINT64 MaxAddress;
923 MAP_ENTRYS *MapEntrys;
924 ALLOCATE_PAGE_RECORDS *PagesRecord;
925 UINTN Index;
926 UNIT_TEST_STATUS TestStatus;
927 RETURN_STATUS Status;
928 IA32_MAP_ENTRY *InitMap;
929 UINTN InitMapCount;
930
931 MaxAddress = GetMaxAddress (PagingMode);
932 PageTable = 0;
933 MapEntrys = AllocatePages (EFI_SIZE_TO_PAGES (1000*sizeof (MAP_ENTRY) + sizeof (MAP_ENTRYS)));
934 ASSERT (MapEntrys != NULL);
935 MapEntrys->Count = 0;
936 MapEntrys->InitCount = 0;
937 MapEntrys->MaxCount = 1000;
938 PagesRecord = AllocatePages (EFI_SIZE_TO_PAGES (1000*sizeof (ALLOCATE_PAGE_RECORD) + sizeof (ALLOCATE_PAGE_RECORDS)));
939 ASSERT (PagesRecord != NULL);
940 PagesRecord->Count = 0;
941 PagesRecord->MaxCount = 1000;
942 PagesRecord->AllocatePagesForPageTable = RecordAllocatePages;
943
944 if (mRandomOption & MANUAL_CHANGE_PAGE_TABLE) {
945 ExpctedEntryNumber = ExpctedEntryNumber/2;
946 }
947
948 for (Index = 0; Index < ExpctedEntryNumber; Index++) {
949 TestStatus = SingleMapEntryTest (
950 &PageTable,
951 PagingMode,
952 MaxAddress,
953 MapEntrys,
954 PagesRecord,
955 NULL,
956 0
957 );
958 if (TestStatus != UNIT_TEST_PASSED) {
959 return TestStatus;
960 }
961 }
962
963 if ((mRandomOption & MANUAL_CHANGE_PAGE_TABLE) != 0) {
964 MapEntrys->InitCount = ExpctedEntryNumber;
965 TestStatus = ValidateAndRandomeModifyPageTable (PageTable, PagingMode);
966 RandomNumber = 0;
967 if (TestStatus != UNIT_TEST_PASSED) {
968 return TestStatus;
969 }
970
971 InitMapCount = 0;
972 Status = PageTableParse (PageTable, PagingMode, NULL, &InitMapCount);
973 if (InitMapCount != 0) {
975
976 //
977 // Allocate memory for Maps
978 // Note the memory is only used in this one Single MapEntry Test
979 //
980 InitMap = AllocatePages (EFI_SIZE_TO_PAGES (InitMapCount * sizeof (IA32_MAP_ENTRY)));
981 ASSERT (InitMap != NULL);
982 Status = PageTableParse (PageTable, PagingMode, InitMap, &InitMapCount);
983 }
984
986 for (Index = 0; Index < ExpctedEntryNumber; Index++) {
987 TestStatus = SingleMapEntryTest (
988 &PageTable,
989 PagingMode,
990 MaxAddress,
991 MapEntrys,
992 PagesRecord,
993 InitMap,
994 InitMapCount
995 );
996 if (TestStatus != UNIT_TEST_PASSED) {
997 return TestStatus;
998 }
999 }
1000
1001 if (InitMapCount != 0) {
1002 FreePages (InitMap, EFI_SIZE_TO_PAGES (InitMapCount*sizeof (IA32_MAP_ENTRY)));
1003 }
1004 }
1005
1006 FreePages (
1007 MapEntrys,
1008 EFI_SIZE_TO_PAGES (1000*sizeof (MAP_ENTRY) + sizeof (MAP_ENTRYS))
1009 );
1010
1011 for (Index = 0; Index < PagesRecord->Count; Index++) {
1012 FreePages (PagesRecord->Records[Index].Buffer, PagesRecord->Records[Index].Pages);
1013 }
1014
1015 FreePages (PagesRecord, EFI_SIZE_TO_PAGES (1000*sizeof (ALLOCATE_PAGE_RECORD) + sizeof (ALLOCATE_PAGE_RECORDS)));
1016
1017 return UNIT_TEST_PASSED;
1018}
1019
1036EFIAPI
1038 IN UNIT_TEST_CONTEXT Context
1039 )
1040{
1041 UNIT_TEST_STATUS Status;
1042 UINTN Index;
1043
1045 UT_ASSERT_EQUAL (Random32 (100, 100), 100);
1046 UT_ASSERT_EQUAL (Random64 (100, 100), 100);
1047 UT_ASSERT_TRUE ((Random32 (9, 10) >= 9) & (Random32 (9, 10) <= 10));
1048 UT_ASSERT_TRUE ((Random64 (9, 10) >= 9) & (Random64 (9, 10) <= 10));
1049 mSupportedBit.Uint64 = 0;
1050 mSupportedBit.Bits.Present = 1;
1051 mSupportedBit.Bits.ReadWrite = 1;
1052 mSupportedBit.Bits.UserSupervisor = 1;
1053 mSupportedBit.Bits.WriteThrough = 1;
1054 mSupportedBit.Bits.CacheDisabled = 1;
1055 mSupportedBit.Bits.Accessed = 1;
1056 mSupportedBit.Bits.Dirty = 1;
1057 mSupportedBit.Bits.Pat = 1;
1058 mSupportedBit.Bits.Global = 1;
1059 mSupportedBit.Bits.ProtectionKey = 0xF;
1060 if (((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->PagingMode == PagingPae) {
1061 mSupportedBit.Bits.ProtectionKey = 0;
1062 }
1063
1064 mSupportedBit.Bits.Nx = 1;
1065
1066 mRandomOption = ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->RandomOption;
1067 mNumberIndex = 0;
1068
1069 for (Index = 0; Index < ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->TestCount; Index++) {
1070 Status = MultipleMapEntryTest (
1071 ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->TestRangeCount,
1072 ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->PagingMode
1073 );
1074 if (Status != UNIT_TEST_PASSED) {
1075 return Status;
1076 }
1077
1078 DEBUG ((DEBUG_INFO, "."));
1079 }
1080
1081 DEBUG ((DEBUG_INFO, "\n"));
1082
1083 return UNIT_TEST_PASSED;
1084}
UINT64 UINTN
BOOLEAN EFIAPI RandomBytes(OUT UINT8 *Output, IN UINTN Size)
Definition: CryptRand.c:76
BOOLEAN EFIAPI RandomSeed(IN CONST UINT8 *Seed OPTIONAL, IN UINTN SeedSize)
Definition: CryptRand.c:36
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
RETURN_STATUS EFIAPI PageTableMap(IN OUT UINTN *PageTable OPTIONAL, IN PAGING_MODE PagingMode, IN VOID *Buffer, IN OUT UINTN *BufferSize, IN UINT64 LinearAddress, IN UINT64 Length, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask, OUT BOOLEAN *IsModified OPTIONAL)
RETURN_STATUS EFIAPI PageTableParse(IN UINTN PageTable, IN PAGING_MODE PagingMode, IN IA32_MAP_ENTRY *Map, IN OUT UINTN *MapCount)
UNIT_TEST_STATUS IsPageTableValid(IN UINTN PageTable, IN PAGING_MODE PagingMode)
Definition: TestHelper.c:170
UINT64 GetMaxAddress(IN PAGING_MODE Mode)
Definition: TestHelper.c:306
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
#define NULL
Definition: Base.h:319
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define MIN(a, b)
Definition: Base.h:1007
#define RETURN_SUCCESS
Definition: Base.h:1066
#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 RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI AllocatePages(IN UINTN Pages)
UINT64 Random64(UINT64 Start, UINT64 Limit)
Definition: RandomTest.c:111
VOID SetRandomStack(VOID)
Definition: RandomTest.c:145
VOID AppendKeyPointToBuffer(IN OUT UINT64 *Buffer, IN OUT UINTN *Count, IN UINT64 Address)
Definition: RandomTest.c:554
BOOLEAN EFIAPI RandomBytesUsingArray(OUT UINT8 *Output, IN UINTN Size)
Definition: RandomTest.c:40
UNIT_TEST_STATUS EFIAPI TestCaseforRandomTest(IN UNIT_TEST_CONTEXT Context)
Definition: RandomTest.c:1037
UNIT_TEST_STATUS ValidateAndRandomeModifyPageTable(IN UINTN PageTable, IN PAGING_MODE PagingMode)
Definition: RandomTest.c:267
UNIT_TEST_STATUS ValidateAndRandomeModifyPageTablePageTableEntry(IN IA32_PAGING_ENTRY *PagingEntry, IN UINTN Level, IN UINTN MaxLeafLevel, IN UINT64 Address)
Definition: RandomTest.c:169
BOOLEAN RandomBoolean(UINT8 Probability)
Definition: RandomTest.c:134
VOID RemoveLastMapEntry(IN OUT MAP_ENTRYS *MapEntrys)
Definition: RandomTest.c:305
VOID GenerateSingleRandomMapEntry(IN UINT64 MaxAddress, IN OUT MAP_ENTRYS *MapEntrys)
Definition: RandomTest.c:329
UINT32 Random32(UINT32 Start, UINT32 Limit)
Definition: RandomTest.c:92
UNIT_TEST_STATUS MultipleMapEntryTest(IN UINTN ExpctedEntryNumber, IN PAGING_MODE PagingMode)
Definition: RandomTest.c:916
BOOLEAN CompareEntrysforOnePoint(IN UINT64 Address, IN MAP_ENTRYS *MapEntrys, IN IA32_MAP_ENTRY *Map, IN UINTN MapCount, IN IA32_MAP_ENTRY *InitMap, IN UINTN InitMapCount)
Definition: RandomTest.c:418
VOID GetKeyPointList(IN MAP_ENTRYS *MapEntrys, IN IA32_MAP_ENTRY *Map, IN UINTN MapCount, IN OUT UINT64 *Buffer, IN OUT UINTN *Count)
Definition: RandomTest.c:583
VOID *EFIAPI RecordAllocatePages(IN ALLOCATE_PAGE_RECORDS *PagesRecord, IN UINTN Pages)
Definition: RandomTest.c:887
BOOLEAN EFIAPI LocalRandomBytes(OUT UINT8 *Output, IN UINTN Size)
Definition: RandomTest.c:72
UNIT_TEST_STATUS SingleMapEntryTest(IN OUT UINTN *PageTable, IN PAGING_MODE PagingMode, IN UINT64 MaxAddress, IN MAP_ENTRYS *MapEntrys, IN ALLOCATE_PAGE_RECORDS *PagesRecord, IN IA32_MAP_ENTRY *InitMap, IN UINTN InitMapCount)
Definition: RandomTest.c:652
UINT64 GetEntryFromPageTable(IN UINTN PageTable, IN PAGING_MODE PagingMode, IN UINT64 Address, OUT UINTN *Level)
Definition: TestHelper.c:267
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define UT_ASSERT_NOT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:402
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