2 BaseRng Library that uses the TimerLib to provide reasonably random numbers.
3 Do not use this on a production system.
5 Copyright (c) Microsoft Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/TimerLib.h>
14 #define DEFAULT_DELAY_TIME_IN_MICROSECONDS 10
17 Using the TimerLib GetPerformanceCounterProperties() we delay
18 for enough time for the PerformanceCounter to increment.
20 If the return value from GetPerformanceCounterProperties (TimerLib)
21 is zero, this function will return 10 and attempt to assert.
25 CalculateMinimumDecentDelayInMicroseconds (
31 // Get the counter properties
32 CounterHz
= GetPerformanceCounterProperties (NULL
, NULL
);
33 // Make sure we won't divide by zero
35 ASSERT(CounterHz
!= 0); // Assert so the developer knows something is wrong
36 return DEFAULT_DELAY_TIME_IN_MICROSECONDS
;
38 // Calculate the minimum delay based on 1.5 microseconds divided by the hertz.
39 // We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds
40 // This ensures that the performance counter has increased by at least one
41 return (UINT32
)(MAX (DivU64x64Remainder (1500000,CounterHz
, NULL
), 1));
46 Generates a 16-bit random number.
48 if Rand is NULL, then ASSERT().
50 @param[out] Rand Buffer pointer to store the 16-bit random value.
52 @retval TRUE Random number generated successfully.
53 @retval FALSE Failed to generate the random number.
64 UINT32 DelayInMicroSeconds
;
66 ASSERT (Rand
!= NULL
);
71 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
72 RandPtr
= (UINT8
*)Rand
;
73 // Get 2 bytes of random ish data
74 for (Index
= 0; Index
< sizeof(UINT16
); Index
++) {
75 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
76 // Delay to give the performance counter a chance to change
77 MicroSecondDelay (DelayInMicroSeconds
);
84 Generates a 32-bit random number.
86 if Rand is NULL, then ASSERT().
88 @param[out] Rand Buffer pointer to store the 32-bit random value.
90 @retval TRUE Random number generated successfully.
91 @retval FALSE Failed to generate the random number.
102 UINT32 DelayInMicroSeconds
;
104 ASSERT (Rand
!= NULL
);
110 RandPtr
= (UINT8
*) Rand
;
111 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
112 // Get 4 bytes of random ish data
113 for (Index
= 0; Index
< sizeof(UINT32
); Index
++) {
114 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
115 // Delay to give the performance counter a chance to change
116 MicroSecondDelay (DelayInMicroSeconds
);
123 Generates a 64-bit random number.
125 if Rand is NULL, then ASSERT().
127 @param[out] Rand Buffer pointer to store the 64-bit random value.
129 @retval TRUE Random number generated successfully.
130 @retval FALSE Failed to generate the random number.
141 UINT32 DelayInMicroSeconds
;
143 ASSERT (Rand
!= NULL
);
149 RandPtr
= (UINT8
*)Rand
;
150 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
151 // Get 8 bytes of random ish data
152 for (Index
= 0; Index
< sizeof(UINT64
); Index
++) {
153 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
154 // Delay to give the performance counter a chance to change
155 MicroSecondDelay (DelayInMicroSeconds
);
163 Generates a 128-bit random number.
165 if Rand is NULL, then ASSERT().
167 @param[out] Rand Buffer pointer to store the 128-bit random value.
169 @retval TRUE Random number generated successfully.
170 @retval FALSE Failed to generate the random number.
179 ASSERT (Rand
!= NULL
);
180 // This should take around 80ms
182 // Read first 64 bits
183 if (!GetRandomNumber64 (Rand
)) {
187 // Read second 64 bits
188 return GetRandomNumber64 (++Rand
);