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
;
39 // Calculate the minimum delay based on 1.5 microseconds divided by the hertz.
40 // We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds
41 // This ensures that the performance counter has increased by at least one
42 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
);
72 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
73 RandPtr
= (UINT8
*)Rand
;
74 // Get 2 bytes of random ish data
75 for (Index
= 0; Index
< sizeof (UINT16
); Index
++) {
76 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
77 // Delay to give the performance counter a chance to change
78 MicroSecondDelay (DelayInMicroSeconds
);
86 Generates a 32-bit random number.
88 if Rand is NULL, then ASSERT().
90 @param[out] Rand Buffer pointer to store the 32-bit random value.
92 @retval TRUE Random number generated successfully.
93 @retval FALSE Failed to generate the random number.
104 UINT32 DelayInMicroSeconds
;
106 ASSERT (Rand
!= NULL
);
112 RandPtr
= (UINT8
*)Rand
;
113 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
114 // Get 4 bytes of random ish data
115 for (Index
= 0; Index
< sizeof (UINT32
); Index
++) {
116 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
117 // Delay to give the performance counter a chance to change
118 MicroSecondDelay (DelayInMicroSeconds
);
126 Generates a 64-bit random number.
128 if Rand is NULL, then ASSERT().
130 @param[out] Rand Buffer pointer to store the 64-bit random value.
132 @retval TRUE Random number generated successfully.
133 @retval FALSE Failed to generate the random number.
144 UINT32 DelayInMicroSeconds
;
146 ASSERT (Rand
!= NULL
);
152 RandPtr
= (UINT8
*)Rand
;
153 DelayInMicroSeconds
= CalculateMinimumDecentDelayInMicroseconds ();
154 // Get 8 bytes of random ish data
155 for (Index
= 0; Index
< sizeof (UINT64
); Index
++) {
156 *RandPtr
= (UINT8
)(GetPerformanceCounter () & 0xFF);
157 // Delay to give the performance counter a chance to change
158 MicroSecondDelay (DelayInMicroSeconds
);
166 Generates a 128-bit random number.
168 if Rand is NULL, then ASSERT().
170 @param[out] Rand Buffer pointer to store the 128-bit random value.
172 @retval TRUE Random number generated successfully.
173 @retval FALSE Failed to generate the random number.
182 ASSERT (Rand
!= NULL
);
183 // This should take around 80ms
185 // Read first 64 bits
186 if (!GetRandomNumber64 (Rand
)) {
190 // Read second 64 bits
191 return GetRandomNumber64 (++Rand
);