2022-06-27 10:58:48 +02:00
/** @file
Random test case for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
2023-03-17 05:09:50 +01:00
Copyright ( c ) 2022 - 2023 , Intel Corporation . All rights reserved . < BR >
2022-06-27 10:58:48 +02:00
SPDX - License - Identifier : BSD - 2 - Clause - Patent
* */
# include "CpuPageTableLibUnitTest.h"
# include "RandomTest.h"
UINTN RandomNumber = 0 ;
extern IA32_PAGING_ENTRY mValidMaskNoLeaf [ 6 ] ;
extern IA32_PAGING_ENTRY mValidMaskLeaf [ 6 ] ;
extern IA32_PAGING_ENTRY mValidMaskLeafFlag [ 6 ] ;
UINTN mRandomOption ;
IA32_MAP_ATTRIBUTE mSupportedBit ;
extern UINTN mNumberCount ;
extern UINT8 mNumbers [ ] ;
UINTN mNumberIndex ;
UINT64 AlignedTable [ ] = {
~ ( ( UINT64 ) SIZE_4KB - 1 ) ,
~ ( ( UINT64 ) SIZE_2MB - 1 ) ,
~ ( ( UINT64 ) SIZE_1GB - 1 )
} ;
/**
Generates a pseudorandom byte stream of the specified size .
Return FALSE to indicate this interface is not supported .
@ param [ out ] Output Pointer to buffer to receive random value .
@ param [ in ] Size Size of random bytes to generate .
@ retval TRUE Always return TRUE
* */
BOOLEAN
EFIAPI
RandomBytesUsingArray (
OUT UINT8 * Output ,
IN UINTN Size
)
{
UINTN Index ;
for ( Index = 0 ; Index < Size ; Index + + ) {
if ( mNumberIndex > = mNumberCount ) {
mNumberIndex = 0 ;
}
Output [ Index ] = mNumbers [ mNumberIndex ] ;
mNumberIndex + + ;
}
return TRUE ;
}
/**
Generates a pseudorandom byte stream of the specified size .
Return FALSE to indicate this interface is not supported .
@ param [ out ] Output Pointer to buffer to receive random value .
@ param [ in ] Size Size of random bytes to generate .
@ retval TRUE Pseudorandom byte stream generated successfully .
@ retval FALSE Pseudorandom number generator fails
* */
BOOLEAN
EFIAPI
LocalRandomBytes (
OUT UINT8 * Output ,
IN UINTN Size
)
{
if ( mRandomOption & USE_RANDOM_ARRAY ) {
return RandomBytesUsingArray ( Output , Size ) ;
} else {
return RandomBytes ( Output , Size ) ;
}
}
/**
Return a 32 bit random number .
@ param Start Start of the random number range .
@ param Limit Limit of the random number range , and return value can be Limit .
@ return 32 bit random number
* */
UINT32
Random32 (
UINT32 Start ,
UINT32 Limit
)
{
UINT64 Value ;
LocalRandomBytes ( ( UINT8 * ) & Value , sizeof ( UINT64 ) ) ;
return ( UINT32 ) ( Value % ( Limit - Start + 1 ) ) + Start ;
}
/**
Return a 64 bit random number .
@ param Start Start of the random number range .
@ param Limit Limit of the random number range , and return value can be Limit .
@ return 64 bit random number
* */
UINT64
Random64 (
UINT64 Start ,
UINT64 Limit
)
{
UINT64 Value ;
LocalRandomBytes ( ( UINT8 * ) & Value , sizeof ( UINT64 ) ) ;
if ( Limit - Start = = MAX_UINT64 ) {
return ( UINT64 ) ( Value ) ;
}
return ( UINT64 ) ( Value % ( Limit - Start + 1 ) ) + Start ;
}
2023-03-17 05:09:50 +01:00
/**
Returns true with the percentage of input Probability .
@ param [ in ] Probability The percentage to return true .
@ return boolean
* */
BOOLEAN
RandomBoolean (
UINT8 Probability
)
{
return ( ( Probability > ( ( UINT8 ) Random64 ( 0 , 100 ) ) ) ? TRUE : FALSE ) ;
}
2022-06-27 10:58:48 +02:00
/**
Check if the Page table entry is valid
@ param [ in ] PagingEntry The entry in page table to verify
@ param [ in ] Level the level of PagingEntry .
@ param [ in ] MaxLeafLevel Max leaf entry level .
@ param [ in ] LinearAddress The linear address verified .
@ retval Leaf entry .
* */
UNIT_TEST_STATUS
ValidateAndRandomeModifyPageTablePageTableEntry (
IN IA32_PAGING_ENTRY * PagingEntry ,
IN UINTN Level ,
IN UINTN MaxLeafLevel ,
IN UINT64 Address
)
{
UINT64 Index ;
2023-03-07 07:21:54 +01:00
UINT32 PageTableBaseAddressLow ;
UINT32 PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
IA32_PAGING_ENTRY * ChildPageEntry ;
UNIT_TEST_STATUS Status ;
if ( PagingEntry - > Pce . Present = = 0 ) {
return UNIT_TEST_PASSED ;
}
if ( ( PagingEntry - > Uint64 & mValidMaskLeafFlag [ Level ] . Uint64 ) = = mValidMaskLeafFlag [ Level ] . Uint64 ) {
//
// It is a Leaf
//
if ( Level > MaxLeafLevel ) {
UT_ASSERT_TRUE ( Level < = MaxLeafLevel ) ;
}
if ( ( PagingEntry - > Uint64 & mValidMaskLeaf [ Level ] . Uint64 ) ! = PagingEntry - > Uint64 ) {
UT_ASSERT_EQUAL ( ( PagingEntry - > Uint64 & mValidMaskLeaf [ Level ] . Uint64 ) , PagingEntry - > Uint64 ) ;
}
2023-03-17 05:09:50 +01:00
if ( ( RandomNumber < 100 ) & & RandomBoolean ( 50 ) ) {
2022-06-27 10:58:48 +02:00
RandomNumber + + ;
if ( Level = = 1 ) {
2023-03-07 07:21:54 +01:00
PageTableBaseAddressLow = PagingEntry - > Pte4K . Bits . PageTableBaseAddressLow ;
PageTableBaseAddressHigh = PagingEntry - > Pte4K . Bits . PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
} else {
2023-03-07 07:21:54 +01:00
PageTableBaseAddressLow = PagingEntry - > PleB . Bits . PageTableBaseAddressLow ;
PageTableBaseAddressHigh = PagingEntry - > PleB . Bits . PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
}
PagingEntry - > Uint64 = ( Random64 ( 0 , MAX_UINT64 ) & mValidMaskLeaf [ Level ] . Uint64 ) | mValidMaskLeafFlag [ Level ] . Uint64 ;
PagingEntry - > Pte4K . Bits . Present = 1 ;
if ( Level = = 1 ) {
2023-03-07 07:21:54 +01:00
PagingEntry - > Pte4K . Bits . PageTableBaseAddressLow = PageTableBaseAddressLow ;
PagingEntry - > Pte4K . Bits . PageTableBaseAddressHigh = PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
} else {
2023-03-07 07:21:54 +01:00
PagingEntry - > PleB . Bits . PageTableBaseAddressLow = PageTableBaseAddressLow ;
PagingEntry - > PleB . Bits . PageTableBaseAddressHigh = PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
}
if ( ( PagingEntry - > Uint64 & mValidMaskLeaf [ Level ] . Uint64 ) ! = PagingEntry - > Uint64 ) {
UT_ASSERT_EQUAL ( ( PagingEntry - > Uint64 & mValidMaskLeaf [ Level ] . Uint64 ) , PagingEntry - > Uint64 ) ;
}
}
return UNIT_TEST_PASSED ;
}
//
// Not a leaf
//
UT_ASSERT_NOT_EQUAL ( Level , 1 ) ;
if ( ( PagingEntry - > Uint64 & mValidMaskNoLeaf [ Level ] . Uint64 ) ! = PagingEntry - > Uint64 ) {
DEBUG ( ( DEBUG_ERROR , " ERROR: Level %d no Leaf entry is 0x%lx, which reserved bit is set \n " , Level , PagingEntry - > Uint64 ) ) ;
UT_ASSERT_EQUAL ( ( PagingEntry - > Uint64 & mValidMaskNoLeaf [ Level ] . Uint64 ) , PagingEntry - > Uint64 ) ;
}
2023-03-17 05:09:50 +01:00
if ( ( RandomNumber < 100 ) & & RandomBoolean ( 50 ) ) {
2022-06-27 10:58:48 +02:00
RandomNumber + + ;
2023-03-07 07:21:54 +01:00
PageTableBaseAddressLow = PagingEntry - > PleB . Bits . PageTableBaseAddressLow ;
PageTableBaseAddressHigh = PagingEntry - > PleB . Bits . PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
2023-03-07 07:21:54 +01:00
PagingEntry - > Uint64 = Random64 ( 0 , MAX_UINT64 ) & mValidMaskNoLeaf [ Level ] . Uint64 ;
PagingEntry - > Pnle . Bits . Present = 1 ;
PagingEntry - > PleB . Bits . PageTableBaseAddressLow = PageTableBaseAddressLow ;
PagingEntry - > PleB . Bits . PageTableBaseAddressHigh = PageTableBaseAddressHigh ;
2022-06-27 10:58:48 +02:00
ASSERT ( ( PagingEntry - > Uint64 & mValidMaskLeafFlag [ Level ] . Uint64 ) ! = mValidMaskLeafFlag [ Level ] . Uint64 ) ;
}
2023-03-07 07:21:54 +01:00
ChildPageEntry = ( IA32_PAGING_ENTRY * ) ( UINTN ) ( IA32_PNLE_PAGE_TABLE_BASE_ADDRESS ( & PagingEntry - > Pnle ) ) ;
2022-06-27 10:58:48 +02:00
for ( Index = 0 ; Index < 512 ; Index + + ) {
Status = ValidateAndRandomeModifyPageTablePageTableEntry ( & ChildPageEntry [ Index ] , Level - 1 , MaxLeafLevel , Address + ( Index < < ( 9 * ( Level - 1 ) + 3 ) ) ) ;
if ( Status ! = UNIT_TEST_PASSED ) {
return Status ;
}
}
return UNIT_TEST_PASSED ;
}
/**
Check if the Page table is valid
@ param [ in ] PageTable The pointer to the page table .
@ param [ in ] PagingMode The paging mode .
@ retval UNIT_TEST_PASSED It is a valid Page Table
* */
UNIT_TEST_STATUS
ValidateAndRandomeModifyPageTable (
IN UINTN PageTable ,
IN PAGING_MODE PagingMode
)
{
UINTN MaxLevel ;
UINTN MaxLeafLevel ;
UINT64 Index ;
UNIT_TEST_STATUS Status ;
IA32_PAGING_ENTRY * PagingEntry ;
2023-03-22 05:14:30 +01:00
if ( ( PagingMode = = Paging32bit ) | | ( PagingMode > = PagingModeMax ) ) {
2022-06-27 10:58:48 +02:00
//
// 32bit paging is never supported.
//
return UNIT_TEST_ERROR_TEST_FAILED ;
}
MaxLeafLevel = ( UINT8 ) PagingMode ;
MaxLevel = ( UINT8 ) ( PagingMode > > 8 ) ;
PagingEntry = ( IA32_PAGING_ENTRY * ) ( UINTN ) PageTable ;
for ( Index = 0 ; Index < 512 ; Index + + ) {
Status = ValidateAndRandomeModifyPageTablePageTableEntry ( & PagingEntry [ Index ] , MaxLevel , MaxLeafLevel , Index < < ( 9 * MaxLevel + 3 ) ) ;
if ( Status ! = UNIT_TEST_PASSED ) {
return Status ;
}
}
return Status ;
}
2023-03-17 08:06:48 +01:00
/**
Remove the last MAP_ENTRY in MapEntrys .
@ param MapEntrys Pointer to MapEntrys buffer
* */
VOID
RemoveLastMapEntry (
IN OUT MAP_ENTRYS * MapEntrys
)
{
UINTN MapsIndex ;
if ( MapEntrys - > Count = = 0 ) {
return ;
}
MapsIndex = MapEntrys - > Count - 1 ;
ZeroMem ( & ( MapEntrys - > Maps [ MapsIndex ] ) , sizeof ( MAP_ENTRY ) ) ;
MapEntrys - > Count = MapsIndex ;
}
2022-06-27 10:58:48 +02:00
/**
Generate single random map entry .
The map entry can be the input of function PageTableMap
the LinearAddress and length is aligned to aligned table .
@ param MaxAddress Max Address .
@ param MapEntrys Output MapEntrys contains all parameter as input of function PageTableMap
* */
VOID
GenerateSingleRandomMapEntry (
IN UINT64 MaxAddress ,
IN OUT MAP_ENTRYS * MapEntrys
)
{
UINTN MapsIndex ;
UINT64 FormerLinearAddress ;
UINT64 FormerLinearAddressBottom ;
UINT64 FormerLinearAddressTop ;
MapsIndex = MapEntrys - > Count ;
ASSERT ( MapsIndex < MapEntrys - > MaxCount ) ;
//
// use AlignedTable to avoid that a random number can be very hard to be 1G or 2M aligned
//
2023-03-17 05:09:50 +01:00
if ( ( MapsIndex ! = 0 ) & & ( RandomBoolean ( 50 ) ) ) {
2022-06-27 10:58:48 +02:00
FormerLinearAddress = MapEntrys - > Maps [ Random32 ( 0 , ( UINT32 ) MapsIndex - 1 ) ] . LinearAddress ;
if ( FormerLinearAddress < 2 * ( UINT64 ) SIZE_1GB ) {
FormerLinearAddressBottom = 0 ;
} else {
FormerLinearAddressBottom = FormerLinearAddress - 2 * ( UINT64 ) SIZE_1GB ;
}
if ( FormerLinearAddress + 2 * ( UINT64 ) SIZE_1GB > MaxAddress ) {
FormerLinearAddressTop = MaxAddress ;
} else {
FormerLinearAddressTop = FormerLinearAddress + 2 * ( UINT64 ) SIZE_1GB ;
}
MapEntrys - > Maps [ MapsIndex ] . LinearAddress = Random64 ( FormerLinearAddressBottom , FormerLinearAddressTop ) & AlignedTable [ Random32 ( 0 , ARRAY_SIZE ( AlignedTable ) - 1 ) ] ;
} else {
MapEntrys - > Maps [ MapsIndex ] . LinearAddress = Random64 ( 0 , MaxAddress ) & AlignedTable [ Random32 ( 0 , ARRAY_SIZE ( AlignedTable ) - 1 ) ] ;
}
//
// To have better performance, limit the size less than 10G
//
MapEntrys - > Maps [ MapsIndex ] . Length = Random64 ( 0 , MIN ( MaxAddress - MapEntrys - > Maps [ MapsIndex ] . LinearAddress , 10 * ( UINT64 ) SIZE_1GB ) ) & AlignedTable [ Random32 ( 0 , ARRAY_SIZE ( AlignedTable ) - 1 ) ] ;
2023-03-17 05:09:50 +01:00
if ( ( MapsIndex ! = 0 ) & & ( RandomBoolean ( 50 ) ) ) {
2022-06-27 10:58:48 +02:00
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 = MapEntrys - > Maps [ Random32 ( 0 , ( UINT32 ) MapsIndex - 1 ) ] . Attribute . Uint64 ;
MapEntrys - > Maps [ MapsIndex ] . Mask . Uint64 = MapEntrys - > Maps [ Random32 ( 0 , ( UINT32 ) MapsIndex - 1 ) ] . Mask . Uint64 ;
} else {
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 = Random64 ( 0 , MAX_UINT64 ) & mSupportedBit . Uint64 ;
2023-03-17 08:06:48 +01:00
if ( RandomBoolean ( 5 ) ) {
//
// The probability to get random Mask should be small since all bits of a random number
// have a high probability of containing 0, which may be a invalid input.
//
MapEntrys - > Maps [ MapsIndex ] . Mask . Uint64 = Random64 ( 0 , MAX_UINT64 ) & mSupportedBit . Uint64 ;
} else {
MapEntrys - > Maps [ MapsIndex ] . Mask . Uint64 = MAX_UINT64 ;
}
2022-06-27 10:58:48 +02:00
if ( MapEntrys - > Maps [ MapsIndex ] . Mask . Bits . ProtectionKey ! = 0 ) {
MapEntrys - > Maps [ MapsIndex ] . Mask . Bits . ProtectionKey = 0xF ;
}
}
if ( mRandomOption & ONLY_ONE_ONE_MAPPING ) {
2023-03-07 07:21:54 +01:00
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 & = ( ~ IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ) ;
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 | = MapEntrys - > Maps [ MapsIndex ] . LinearAddress ;
MapEntrys - > Maps [ MapsIndex ] . Mask . Uint64 | = IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ;
2022-06-27 10:58:48 +02:00
} else {
2023-03-07 07:21:54 +01:00
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 & = ( ~ IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ) ;
MapEntrys - > Maps [ MapsIndex ] . Attribute . Uint64 | = ( Random64 ( 0 , ( ( ( UINT64 ) 1 ) < < 52 ) - 1 ) & AlignedTable [ Random32 ( 0 , ARRAY_SIZE ( AlignedTable ) - 1 ) ] ) ;
2022-06-27 10:58:48 +02:00
}
MapEntrys - > Count + = 1 ;
}
/**
Compare the attribute for one point .
MapEntrys records every memory ranges that is used as input
Map and MapCount are gotten from Page table
Compare if this point have same attribute .
@ param [ in ] Address Address of one Point .
@ param [ in ] MapEntrys Record every memory ranges that is used as input
@ param [ in ] Map Pointer to an array that describes multiple linear address ranges .
@ param [ in ] MapCount Pointer to a UINTN that hold the number of entries in the Map .
@ param [ in ] InitMap Pointer to an array that describes init map entries .
@ param [ in ] InitMapCount Pointer to a UINTN that hold the number of init map entries .
@ retval TRUE At least one byte of data is available to be read
@ retval FALSE No data is available to be read
* */
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
)
{
UINTN Index ;
IA32_MAP_ATTRIBUTE AttributeInInitMap ;
IA32_MAP_ATTRIBUTE AttributeInMap ;
IA32_MAP_ATTRIBUTE AttributeInMapEntrys ;
IA32_MAP_ATTRIBUTE MaskInMapEntrys ;
AttributeInMap . Uint64 = 0 ;
AttributeInMapEntrys . Uint64 = 0 ;
AttributeInInitMap . Uint64 = 0 ;
MaskInMapEntrys . Uint64 = 0 ;
//
// Assume every entry in maps does not overlap with each other
//
for ( Index = 0 ; Index < MapCount ; Index + + ) {
if ( ( Address > = Map [ Index ] . LinearAddress ) & & ( Address < ( Map [ Index ] . LinearAddress + Map [ Index ] . Length ) ) ) {
2023-03-07 07:21:54 +01:00
AttributeInMap . Uint64 = ( Map [ Index ] . Attribute . Uint64 & mSupportedBit . Uint64 ) ;
AttributeInMap . Uint64 & = ( ~ IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ) ;
AttributeInMap . Uint64 | = ( Address - Map [ Index ] . LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS ( & Map [ Index ] . Attribute ) ) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ;
2022-06-27 10:58:48 +02:00
break ;
}
}
//
// Assume every entry in maps does not overlap with each other
//
for ( Index = 0 ; Index < InitMapCount ; Index + + ) {
if ( ( Address > = InitMap [ Index ] . LinearAddress ) & & ( Address < ( InitMap [ Index ] . LinearAddress + InitMap [ Index ] . Length ) ) ) {
2023-03-07 07:21:54 +01:00
AttributeInInitMap . Uint64 = ( InitMap [ Index ] . Attribute . Uint64 & mSupportedBit . Uint64 ) ;
AttributeInInitMap . Uint64 & = ( ~ IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ) ;
AttributeInInitMap . Uint64 | = ( Address - InitMap [ Index ] . LinearAddress + IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS ( & InitMap [ Index ] . Attribute ) ) & IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ;
2022-06-27 10:58:48 +02:00
break ;
}
}
AttributeInMapEntrys . Uint64 = AttributeInInitMap . Uint64 ;
for ( Index = MapEntrys - > InitCount ; Index < MapEntrys - > Count ; Index + + ) {
if ( ( Address > = MapEntrys - > Maps [ Index ] . LinearAddress ) & & ( Address < ( MapEntrys - > Maps [ Index ] . LinearAddress + MapEntrys - > Maps [ Index ] . Length ) ) ) {
if ( AttributeInMapEntrys . Bits . Present = = 0 ) {
AttributeInMapEntrys . Uint64 = 0 ;
MaskInMapEntrys . Uint64 = 0 ;
}
MaskInMapEntrys . Uint64 | = MapEntrys - > Maps [ Index ] . Mask . Uint64 ;
AttributeInMapEntrys . Uint64 & = ( ~ MapEntrys - > Maps [ Index ] . Mask . Uint64 ) ;
AttributeInMapEntrys . Uint64 | = ( MapEntrys - > Maps [ Index ] . Attribute . Uint64 & MapEntrys - > Maps [ Index ] . Mask . Uint64 ) ;
2023-03-07 07:21:54 +01:00
if ( IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS ( & MapEntrys - > Maps [ Index ] . Mask ) ! = 0 ) {
AttributeInMapEntrys . Uint64 & = ( ~ IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS_MASK ) ;
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 ;
2022-06-27 10:58:48 +02:00
}
}
}
if ( AttributeInMap . Bits . Present = = 0 ) {
if ( AttributeInMapEntrys . Bits . Present = = 0 ) {
return TRUE ;
}
}
if ( ( AttributeInMap . Uint64 & MaskInMapEntrys . Uint64 ) ! = ( AttributeInMapEntrys . Uint64 & MaskInMapEntrys . Uint64 ) ) {
DEBUG ( ( DEBUG_INFO , " ======detailed information begin===== \n " ) ) ;
DEBUG ( ( DEBUG_INFO , " \n Error: Detect different attribute on a point with linear address: 0x%lx \n " , Address ) ) ;
2023-03-07 07:21:54 +01:00
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 ) ) ) ;
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 ) ) ) ;
2022-06-27 10:58:48 +02:00
DEBUG ( ( DEBUG_INFO , " The total Mask is 0x%lx \n " , MaskInMapEntrys . Uint64 ) ) ;
if ( MapEntrys - > InitCount ! = 0 ) {
DEBUG ( ( DEBUG_INFO , " Below is the initialization status: \n " ) ) ;
for ( Index = 0 ; Index < InitMapCount ; Index + + ) {
if ( ( Address > = InitMap [ Index ] . LinearAddress ) & & ( Address < ( InitMap [ Index ] . LinearAddress + InitMap [ Index ] . Length ) ) ) {
DEBUG ( ( DEBUG_INFO , " * " ) ) ;
} else {
DEBUG ( ( DEBUG_INFO , " " ) ) ;
}
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 ) ) ;
}
}
DEBUG ( ( DEBUG_INFO , " Below is the inputs: \n " ) ) ;
DEBUG ( ( DEBUG_INFO , " Index: {LinearAddress, LinearLimit, Mask, Attribute} \n " ) ) ;
for ( Index = MapEntrys - > InitCount ; Index < MapEntrys - > Count ; Index + + ) {
if ( ( Address > = MapEntrys - > Maps [ Index ] . LinearAddress ) & & ( Address < ( MapEntrys - > Maps [ Index ] . LinearAddress + MapEntrys - > Maps [ Index ] . Length ) ) ) {
DEBUG ( ( DEBUG_INFO , " * " ) ) ;
} else {
DEBUG ( ( DEBUG_INFO , " " ) ) ;
}
DEBUG ( (
DEBUG_INFO ,
" %02d: {0x%lx, 0x%lx, 0x%lx,0x%lx} \n " ,
Index ,
MapEntrys - > Maps [ Index ] . LinearAddress ,
MapEntrys - > Maps [ Index ] . LinearAddress + MapEntrys - > Maps [ Index ] . Length ,
MapEntrys - > Maps [ Index ] . Mask . Uint64 ,
MapEntrys - > Maps [ Index ] . Attribute . Uint64
) ) ;
}
DEBUG ( ( DEBUG_INFO , " Below is the dumped from pagetable: \n " ) ) ;
for ( Index = 0 ; Index < MapCount ; Index + + ) {
if ( ( Address > = Map [ Index ] . LinearAddress ) & & ( Address < ( Map [ Index ] . LinearAddress + Map [ Index ] . Length ) ) ) {
DEBUG ( ( DEBUG_INFO , " * " ) ) ;
} else {
DEBUG ( ( DEBUG_INFO , " " ) ) ;
}
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 ) ) ;
}
DEBUG ( ( DEBUG_INFO , " ======detailed information done===== \n " ) ) ;
return FALSE ;
}
return TRUE ;
}
/**
Append key point of a given address to Buffer
if buffer is NULL , only count needed count
@ param [ in , out ] Buffer Buffer to contains all key point .
@ param [ in , out ] Count Count of the key point .
@ param [ in ] Address given address
* */
VOID
AppendKeyPointToBuffer (
IN OUT UINT64 * Buffer ,
IN OUT UINTN * Count ,
IN UINT64 Address
)
{
if ( Buffer ! = NULL ) {
Buffer [ * Count ] = Address ;
( * Count ) + + ;
Buffer [ * Count ] = Address + 1 ;
( * Count ) + + ;
Buffer [ * Count ] = Address - 1 ;
( * Count ) + + ;
} else {
( * Count ) = ( * Count ) + 3 ;
}
}
/**
Get all key points from a buffer
if buffer is NULL , only count needed count
@ param [ in ] MapEntrys Record every memory ranges that is used as input
@ param [ in ] Map Pointer to an array that describes multiple linear address ranges .
@ param [ in ] MapCount Pointer to a UINTN that hold the actual number of entries in the Map .
@ param [ in , out ] Buffer Buffer to contains all key point .
@ param [ in , out ] Count Count of the key point .
* */
VOID
GetKeyPointList (
IN MAP_ENTRYS * MapEntrys ,
IN IA32_MAP_ENTRY * Map ,
IN UINTN MapCount ,
IN OUT UINT64 * Buffer ,
IN OUT UINTN * Count
)
{
UINTN TemCount ;
UINTN Index1 ;
UINTN Index2 ;
TemCount = 0 ;
for ( Index1 = 0 ; Index1 < MapEntrys - > Count ; Index1 + + ) {
AppendKeyPointToBuffer ( Buffer , & TemCount , MapEntrys - > Maps [ Index1 ] . LinearAddress ) ;
AppendKeyPointToBuffer ( Buffer , & TemCount , MapEntrys - > Maps [ Index1 ] . LinearAddress + MapEntrys - > Maps [ Index1 ] . Length ) ;
}
for ( Index2 = 0 ; Index2 < MapCount ; Index2 + + ) {
if ( Buffer ! = NULL ) {
for ( Index1 = 0 ; Index1 < TemCount ; Index1 + + ) {
if ( Buffer [ Index1 ] = = Map [ Index2 ] . LinearAddress ) {
break ;
}
}
if ( Index1 < TemCount ) {
continue ;
}
}
AppendKeyPointToBuffer ( Buffer , & TemCount , Map [ Index2 ] . LinearAddress ) ;
}
for ( Index2 = 0 ; Index2 < MapCount ; Index2 + + ) {
if ( Buffer ! = NULL ) {
for ( Index1 = 0 ; Index1 < TemCount ; Index1 + + ) {
if ( Buffer [ Index1 ] = = ( Map [ Index2 ] . LinearAddress + Map [ Index2 ] . Length ) ) {
break ;
}
}
if ( Index1 < TemCount ) {
continue ;
}
}
AppendKeyPointToBuffer ( Buffer , & TemCount , Map [ Index2 ] . LinearAddress + Map [ Index2 ] . Length ) ;
}
* Count = TemCount ;
}
/**
Generate random one range with randome attribute , and add it into pagetable
Compare the key point has same attribute
@ param [ in , out ] PageTable The pointer to the page table to update , or pointer to NULL if a new page table is to be created .
@ param [ in ] PagingMode The paging mode .
@ param [ in ] MaxAddress Max Address .
@ param [ in ] MapEntrys Record every memory ranges that is used as input
@ param [ in ] PagesRecord Used to record memory usage for page table .
@ param [ in ] InitMap Pointer to an array that describes init map entries .
@ param [ in ] InitMapCount Pointer to a UINTN that hold the number of init map entries .
@ retval UNIT_TEST_PASSED The test is successful .
* */
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
)
{
2023-03-17 08:06:48 +01:00
UINTN MapsIndex ;
RETURN_STATUS Status ;
UINTN PageTableBufferSize ;
VOID * Buffer ;
IA32_MAP_ENTRY * Map ;
UINTN MapCount ;
2023-03-07 08:25:27 +01:00
IA32_MAP_ENTRY * Map2 ;
UINTN MapCount2 ;
2023-03-17 08:06:48 +01:00
UINTN Index ;
UINTN KeyPointCount ;
UINTN NewKeyPointCount ;
UINT64 * KeyPointBuffer ;
UINTN Level ;
UINT64 Value ;
UNIT_TEST_STATUS TestStatus ;
MAP_ENTRY * LastMapEntry ;
IA32_MAP_ATTRIBUTE * Mask ;
IA32_MAP_ATTRIBUTE * Attribute ;
UINT64 LastNotPresentRegionStart ;
BOOLEAN IsNotPresent ;
2023-03-07 08:25:27 +01:00
BOOLEAN IsModified ;
2023-03-17 08:06:48 +01:00
MapsIndex = MapEntrys - > Count ;
MapCount = 0 ;
LastNotPresentRegionStart = 0 ;
IsNotPresent = FALSE ;
2023-03-07 08:25:27 +01:00
IsModified = FALSE ;
2022-06-27 10:58:48 +02:00
GenerateSingleRandomMapEntry ( MaxAddress , MapEntrys ) ;
2023-03-24 05:12:44 +01:00
LastMapEntry = & MapEntrys - > Maps [ MapsIndex ] ;
2023-03-17 08:06:48 +01:00
Status = PageTableParse ( * PageTable , PagingMode , NULL , & MapCount ) ;
if ( MapCount ! = 0 ) {
UT_ASSERT_EQUAL ( Status , RETURN_BUFFER_TOO_SMALL ) ;
Map = AllocatePages ( EFI_SIZE_TO_PAGES ( MapCount * sizeof ( IA32_MAP_ENTRY ) ) ) ;
ASSERT ( Map ! = NULL ) ;
Status = PageTableParse ( * PageTable , PagingMode , Map , & MapCount ) ;
}
//
// Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range.
//
if ( LastMapEntry - > Length > 0 ) {
for ( Index = 0 ; Index < MapCount ; Index + + ) {
if ( ( LastNotPresentRegionStart < Map [ Index ] . LinearAddress ) & &
( LastMapEntry - > LinearAddress < Map [ Index ] . LinearAddress ) & & ( LastMapEntry - > LinearAddress + LastMapEntry - > Length > LastNotPresentRegionStart ) )
{
//
// MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table.
//
break ;
}
LastNotPresentRegionStart = Map [ Index ] . LinearAddress + Map [ Index ] . Length ;
}
//
// Either LastMapEntry overlaps with the not-present region in the very end
// Or it overlaps with one in the middle
if ( LastNotPresentRegionStart < LastMapEntry - > LinearAddress + LastMapEntry - > Length ) {
IsNotPresent = TRUE ;
}
}
2022-06-27 10:58:48 +02:00
PageTableBufferSize = 0 ;
Status = PageTableMap (
PageTable ,
PagingMode ,
NULL ,
& PageTableBufferSize ,
2023-03-24 05:12:44 +01:00
LastMapEntry - > LinearAddress ,
LastMapEntry - > Length ,
& LastMapEntry - > Attribute ,
2022-12-09 03:36:37 +01:00
& LastMapEntry - > Mask ,
2023-03-07 08:25:27 +01:00
& IsModified
2022-06-27 10:58:48 +02:00
) ;
2023-03-17 08:06:48 +01:00
Attribute = & LastMapEntry - > Attribute ;
Mask = & LastMapEntry - > Mask ;
//
// If set [LinearAddress, LinearAddress+Attribute] to not preset, all
// other attributes should not be provided.
//
if ( ( LastMapEntry - > Length > 0 ) & & ( Attribute - > Bits . Present = = 0 ) & & ( Mask - > Bits . Present = = 1 ) & & ( Mask - > Uint64 > 1 ) ) {
RemoveLastMapEntry ( MapEntrys ) ;
UT_ASSERT_EQUAL ( Status , RETURN_INVALID_PARAMETER ) ;
return UNIT_TEST_PASSED ;
}
//
// Return Status for non-present range also should be InvalidParameter when:
// 1. Some of attributes are not provided when mapping non-present range to present.
// 2. Set any other attribute without setting the non-present range to Present.
//
if ( IsNotPresent ) {
if ( ( Mask - > Bits . Present = = 1 ) & & ( Attribute - > Bits . Present = = 1 ) ) {
//
// Creating new page table or remapping non-present range to present.
//
if ( ( Mask - > Bits . ReadWrite = = 0 ) | | ( Mask - > Bits . UserSupervisor = = 0 ) | | ( Mask - > Bits . WriteThrough = = 0 ) | | ( Mask - > Bits . CacheDisabled = = 0 ) | |
( Mask - > Bits . Accessed = = 0 ) | | ( Mask - > Bits . Dirty = = 0 ) | | ( Mask - > Bits . Pat = = 0 ) | | ( Mask - > Bits . Global = = 0 ) | |
2023-03-07 07:21:54 +01:00
( ( Mask - > Bits . PageTableBaseAddressLow = = 0 ) & & ( Mask - > Bits . PageTableBaseAddressHigh = = 0 ) ) | | ( Mask - > Bits . ProtectionKey = = 0 ) | | ( Mask - > Bits . Nx = = 0 ) )
2023-03-17 08:06:48 +01:00
{
RemoveLastMapEntry ( MapEntrys ) ;
UT_ASSERT_EQUAL ( Status , RETURN_INVALID_PARAMETER ) ;
return UNIT_TEST_PASSED ;
}
} else if ( ( Mask - > Bits . Present = = 0 ) & & ( Mask - > Uint64 > 1 ) ) {
//
// Only change other attributes for non-present range is not permitted.
//
RemoveLastMapEntry ( MapEntrys ) ;
UT_ASSERT_EQUAL ( Status , RETURN_INVALID_PARAMETER ) ;
return UNIT_TEST_PASSED ;
}
}
2022-06-27 10:58:48 +02:00
if ( PageTableBufferSize ! = 0 ) {
UT_ASSERT_EQUAL ( Status , RETURN_BUFFER_TOO_SMALL ) ;
//
// Allocate memory for Page table
// Note the memory is used in one complete Random test.
//
Buffer = PagesRecord - > AllocatePagesForPageTable ( PagesRecord , EFI_SIZE_TO_PAGES ( PageTableBufferSize ) ) ;
UT_ASSERT_NOT_EQUAL ( Buffer , NULL ) ;
Status = PageTableMap (
PageTable ,
PagingMode ,
Buffer ,
& PageTableBufferSize ,
2023-03-24 05:12:44 +01:00
LastMapEntry - > LinearAddress ,
LastMapEntry - > Length ,
& LastMapEntry - > Attribute ,
2022-12-09 03:36:37 +01:00
& LastMapEntry - > Mask ,
2023-03-07 08:25:27 +01:00
& IsModified
2022-06-27 10:58:48 +02:00
) ;
}
if ( Status ! = RETURN_SUCCESS ) {
UT_ASSERT_EQUAL ( Status , RETURN_SUCCESS ) ;
}
UT_ASSERT_EQUAL ( Status , RETURN_SUCCESS ) ;
TestStatus = IsPageTableValid ( * PageTable , PagingMode ) ;
if ( TestStatus ! = UNIT_TEST_PASSED ) {
return TestStatus ;
}
2023-03-07 08:25:27 +01:00
MapCount2 = 0 ;
Status = PageTableParse ( * PageTable , PagingMode , NULL , & MapCount2 ) ;
if ( MapCount2 ! = 0 ) {
2022-06-27 10:58:48 +02:00
UT_ASSERT_EQUAL ( Status , RETURN_BUFFER_TOO_SMALL ) ;
//
2023-03-07 08:25:27 +01:00
// Allocate memory for Map2
2022-06-27 10:58:48 +02:00
// Note the memory is only used in this one Single MapEntry Test
//
2023-03-07 08:25:27 +01:00
Map2 = AllocatePages ( EFI_SIZE_TO_PAGES ( MapCount2 * sizeof ( IA32_MAP_ENTRY ) ) ) ;
ASSERT ( Map2 ! = NULL ) ;
Status = PageTableParse ( * PageTable , PagingMode , Map2 , & MapCount2 ) ;
}
//
// Check if PageTable has been modified.
//
if ( MapCount2 ! = MapCount ) {
UT_ASSERT_EQUAL ( IsModified , TRUE ) ;
} else {
if ( CompareMem ( Map , Map2 , MapCount2 * sizeof ( IA32_MAP_ENTRY ) ) ! = 0 ) {
UT_ASSERT_EQUAL ( IsModified , TRUE ) ;
} else {
UT_ASSERT_EQUAL ( IsModified , FALSE ) ;
}
2022-06-27 10:58:48 +02:00
}
UT_ASSERT_EQUAL ( Status , RETURN_SUCCESS ) ;
//
// Allocate memory to record all key point
// Note the memory is only used in this one Single MapEntry Test
//
KeyPointCount = 0 ;
2023-03-07 08:25:27 +01:00
GetKeyPointList ( MapEntrys , Map2 , MapCount2 , NULL , & KeyPointCount ) ;
2022-06-27 10:58:48 +02:00
KeyPointBuffer = AllocatePages ( EFI_SIZE_TO_PAGES ( KeyPointCount * sizeof ( UINT64 ) ) ) ;
ASSERT ( KeyPointBuffer ! = NULL ) ;
NewKeyPointCount = 0 ;
2023-03-07 08:25:27 +01:00
GetKeyPointList ( MapEntrys , Map2 , MapCount2 , KeyPointBuffer , & NewKeyPointCount ) ;
2022-06-27 10:58:48 +02:00
//
// Compare all key point's attribute
//
for ( Index = 0 ; Index < NewKeyPointCount ; Index + + ) {
2023-03-07 08:25:27 +01:00
if ( ! CompareEntrysforOnePoint ( KeyPointBuffer [ Index ] , MapEntrys , Map2 , MapCount2 , InitMap , InitMapCount ) ) {
2022-06-27 10:58:48 +02:00
DEBUG ( ( DEBUG_INFO , " Error happens at below key point \n " ) ) ;
DEBUG ( ( DEBUG_INFO , " Index = %d KeyPointBuffer[Index] = 0x%lx \n " , Index , KeyPointBuffer [ Index ] ) ) ;
Value = GetEntryFromPageTable ( * PageTable , PagingMode , KeyPointBuffer [ Index ] , & Level ) ;
DEBUG ( ( DEBUG_INFO , " From Page table, this key point is in level %d entry, with entry value is 0x%lx \n " , Level , Value ) ) ;
UT_ASSERT_TRUE ( FALSE ) ;
}
}
FreePages ( KeyPointBuffer , EFI_SIZE_TO_PAGES ( KeyPointCount * sizeof ( UINT64 ) ) ) ;
if ( MapCount ! = 0 ) {
FreePages ( Map , EFI_SIZE_TO_PAGES ( MapCount * sizeof ( IA32_MAP_ENTRY ) ) ) ;
}
2023-03-07 08:25:27 +01:00
if ( MapCount2 ! = 0 ) {
FreePages ( Map2 , EFI_SIZE_TO_PAGES ( MapCount2 * sizeof ( IA32_MAP_ENTRY ) ) ) ;
}
2022-06-27 10:58:48 +02:00
return UNIT_TEST_PASSED ;
}
/**
Allocate page and record the information in PagesRecord
@ param [ in ] PagesRecord Point to a struct to record memory usage
@ param [ in ] Pages Page count needed to allocate
@ return A pointer to the allocated buffer or NULL if allocation fails .
* */
VOID *
EFIAPI
RecordAllocatePages (
IN ALLOCATE_PAGE_RECORDS * PagesRecord ,
IN UINTN Pages
)
{
VOID * Buffer ;
Buffer = NULL ;
if ( PagesRecord - > Count < PagesRecord - > MaxCount ) {
Buffer = AllocatePages ( Pages ) ;
PagesRecord - > Records [ PagesRecord - > Count ] . Buffer = Buffer ;
PagesRecord - > Records [ PagesRecord - > Count ] . Pages = Pages ;
PagesRecord - > Count + + ;
}
ASSERT ( Buffer ! = NULL ) ;
return Buffer ;
}
/**
The function is a whole Random test , it will call SingleMapEntryTest for ExpctedEntryNumber times
@ param [ in ] ExpctedEntryNumber The count of random entry
@ param [ in ] PagingMode The paging mode .
@ retval UNIT_TEST_PASSED The test is successful .
* */
UNIT_TEST_STATUS
MultipleMapEntryTest (
IN UINTN ExpctedEntryNumber ,
IN PAGING_MODE PagingMode
)
{
UINTN PageTable ;
UINT64 MaxAddress ;
MAP_ENTRYS * MapEntrys ;
ALLOCATE_PAGE_RECORDS * PagesRecord ;
UINTN Index ;
UNIT_TEST_STATUS TestStatus ;
RETURN_STATUS Status ;
IA32_MAP_ENTRY * InitMap ;
UINTN InitMapCount ;
MaxAddress = GetMaxAddress ( PagingMode ) ;
PageTable = 0 ;
MapEntrys = AllocatePages ( EFI_SIZE_TO_PAGES ( 1000 * sizeof ( MAP_ENTRY ) + sizeof ( MAP_ENTRYS ) ) ) ;
ASSERT ( MapEntrys ! = NULL ) ;
MapEntrys - > Count = 0 ;
MapEntrys - > InitCount = 0 ;
MapEntrys - > MaxCount = 1000 ;
PagesRecord = AllocatePages ( EFI_SIZE_TO_PAGES ( 1000 * sizeof ( ALLOCATE_PAGE_RECORD ) + sizeof ( ALLOCATE_PAGE_RECORDS ) ) ) ;
ASSERT ( PagesRecord ! = NULL ) ;
PagesRecord - > Count = 0 ;
PagesRecord - > MaxCount = 1000 ;
PagesRecord - > AllocatePagesForPageTable = RecordAllocatePages ;
if ( mRandomOption & MANUAL_CHANGE_PAGE_TABLE ) {
ExpctedEntryNumber = ExpctedEntryNumber / 2 ;
}
for ( Index = 0 ; Index < ExpctedEntryNumber ; Index + + ) {
TestStatus = SingleMapEntryTest (
& PageTable ,
PagingMode ,
MaxAddress ,
MapEntrys ,
PagesRecord ,
NULL ,
0
) ;
if ( TestStatus ! = UNIT_TEST_PASSED ) {
return TestStatus ;
}
}
if ( ( mRandomOption & MANUAL_CHANGE_PAGE_TABLE ) ! = 0 ) {
MapEntrys - > InitCount = ExpctedEntryNumber ;
TestStatus = ValidateAndRandomeModifyPageTable ( PageTable , PagingMode ) ;
RandomNumber = 0 ;
if ( TestStatus ! = UNIT_TEST_PASSED ) {
return TestStatus ;
}
InitMapCount = 0 ;
Status = PageTableParse ( PageTable , PagingMode , NULL , & InitMapCount ) ;
if ( InitMapCount ! = 0 ) {
UT_ASSERT_EQUAL ( Status , RETURN_BUFFER_TOO_SMALL ) ;
//
// Allocate memory for Maps
// Note the memory is only used in this one Single MapEntry Test
//
InitMap = AllocatePages ( EFI_SIZE_TO_PAGES ( InitMapCount * sizeof ( IA32_MAP_ENTRY ) ) ) ;
ASSERT ( InitMap ! = NULL ) ;
Status = PageTableParse ( PageTable , PagingMode , InitMap , & InitMapCount ) ;
}
UT_ASSERT_EQUAL ( Status , RETURN_SUCCESS ) ;
for ( Index = 0 ; Index < ExpctedEntryNumber ; Index + + ) {
TestStatus = SingleMapEntryTest (
& PageTable ,
PagingMode ,
MaxAddress ,
MapEntrys ,
PagesRecord ,
InitMap ,
InitMapCount
) ;
if ( TestStatus ! = UNIT_TEST_PASSED ) {
return TestStatus ;
}
}
if ( InitMapCount ! = 0 ) {
FreePages ( InitMap , EFI_SIZE_TO_PAGES ( InitMapCount * sizeof ( IA32_MAP_ENTRY ) ) ) ;
}
}
FreePages (
MapEntrys ,
EFI_SIZE_TO_PAGES ( 1000 * sizeof ( MAP_ENTRY ) + sizeof ( MAP_ENTRYS ) )
) ;
for ( Index = 0 ; Index < PagesRecord - > Count ; Index + + ) {
FreePages ( PagesRecord - > Records [ Index ] . Buffer , PagesRecord - > Records [ Index ] . Pages ) ;
}
FreePages ( PagesRecord , EFI_SIZE_TO_PAGES ( 1000 * sizeof ( ALLOCATE_PAGE_RECORD ) + sizeof ( ALLOCATE_PAGE_RECORDS ) ) ) ;
return UNIT_TEST_PASSED ;
}
/**
Random Test
@ param [ in ] Context [ Optional ] An optional parameter that enables :
1 ) test - case reuse with varied parameters and
2 ) test - case re - entry for Target tests that need a
reboot . This parameter is a VOID * and it is the
responsibility of the test author to ensure that the
contents are well understood by all test cases that may
consume it .
@ retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful .
@ retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed .
* */
UNIT_TEST_STATUS
EFIAPI
TestCaseforRandomTest (
IN UNIT_TEST_CONTEXT Context
)
{
UNIT_TEST_STATUS Status ;
UINTN Index ;
UT_ASSERT_EQUAL ( RandomSeed ( NULL , 0 ) , TRUE ) ;
UT_ASSERT_EQUAL ( Random32 ( 100 , 100 ) , 100 ) ;
UT_ASSERT_EQUAL ( Random64 ( 100 , 100 ) , 100 ) ;
UT_ASSERT_TRUE ( ( Random32 ( 9 , 10 ) > = 9 ) & ( Random32 ( 9 , 10 ) < = 10 ) ) ;
UT_ASSERT_TRUE ( ( Random64 ( 9 , 10 ) > = 9 ) & ( Random64 ( 9 , 10 ) < = 10 ) ) ;
2023-03-07 07:21:54 +01:00
mSupportedBit . Uint64 = 0 ;
mSupportedBit . Bits . Present = 1 ;
mSupportedBit . Bits . ReadWrite = 1 ;
mSupportedBit . Bits . UserSupervisor = 1 ;
mSupportedBit . Bits . WriteThrough = 1 ;
mSupportedBit . Bits . CacheDisabled = 1 ;
mSupportedBit . Bits . Accessed = 1 ;
mSupportedBit . Bits . Dirty = 1 ;
mSupportedBit . Bits . Pat = 1 ;
mSupportedBit . Bits . Global = 1 ;
mSupportedBit . Bits . ProtectionKey = 0xF ;
mSupportedBit . Bits . Nx = 1 ;
2022-06-27 10:58:48 +02:00
mRandomOption = ( ( CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT * ) Context ) - > RandomOption ;
mNumberIndex = 0 ;
for ( Index = 0 ; Index < ( ( CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT * ) Context ) - > TestCount ; Index + + ) {
Status = MultipleMapEntryTest (
( ( CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT * ) Context ) - > TestRangeCount ,
( ( CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT * ) Context ) - > PagingMode
) ;
if ( Status ! = UNIT_TEST_PASSED ) {
return Status ;
}
DEBUG ( ( DEBUG_INFO , " . " ) ) ;
}
DEBUG ( ( DEBUG_INFO , " \n " ) ) ;
return UNIT_TEST_PASSED ;
}