PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
rand.c
Go to the documentation of this file.
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/log/log.h>
6
7#include <stdbool.h>
8#include <stdint.h>
9#include <string.h>
10#include <sys/cpuid.h>
11
12static atomic_uint64_t seed = ATOMIC_VAR_INIT(0x123456789ABCDEF0);
13
15{
16 for (uint64_t i = 0; i < size; i++)
17 {
18 uint64_t currentSeed = atomic_load(&seed) + clock_uptime();
19 currentSeed ^= currentSeed << 13;
20 currentSeed ^= currentSeed >> 7;
21 currentSeed ^= currentSeed << 17;
22 atomic_store(&seed, currentSeed);
23 ((uint8_t*)buffer)[i] = (uint8_t)(currentSeed & 0xFF);
24 }
25
26 return 0;
27}
28
30{
31 rand_cpu_t* ctx = SELF_PTR(pcpu_rand);
32
34 cpuid_feature_info(&info);
35
36 ctx->rdrandAvail = (info.featuresEcx & CPUID_ECX_RDRAND) != 0;
37
38 if (!ctx->rdrandAvail)
39 {
40 return;
41 }
42
43 uint64_t prev = UINT64_MAX;
44 uint32_t test;
45 for (uint64_t i = 0; i < 10; i++)
46 {
47 if (rdrand_do(&test, 100) == ERR)
48 {
49 LOG_WARN("cpu%d rdrand instruction failed, disabling\n", SELF->id);
50 ctx->rdrandAvail = false;
51 return;
52 }
53
54 if (prev != UINT64_MAX && prev == test)
55 {
56 LOG_WARN("cpu%d rdrand producing same value repeatedly, disabling\n", SELF->id);
57 ctx->rdrandAvail = false;
58 return;
59 }
60 prev = test;
61 }
62}
63
65{
66 CLI_SCOPE();
67
68 if (!pcpu_rand->rdrandAvail)
69 {
70 return rand_gen_fallback(buffer, size);
71 }
72
73 uint8_t* ptr = (uint8_t*)buffer;
74 uint64_t remaining = size;
75 while (remaining >= sizeof(uint32_t))
76 {
77 uint32_t value;
78 if (rdrand_do(&value, 100) == ERR)
79 {
80 return ERR;
81 }
82 memcpy(ptr, &value, sizeof(uint32_t));
83 ptr += sizeof(uint32_t);
84 remaining -= sizeof(uint32_t);
85 }
86
87 if (remaining > 0)
88 {
89 uint32_t value;
90 if (rdrand_do(&value, 100) == ERR)
91 {
92 return ERR;
93 }
94 memcpy(ptr, &value, remaining);
95 }
96
97 return 0;
98}
EFI_PHYSICAL_ADDRESS buffer
Definition main.c:237
#define CLI_SCOPE()
Macro to increment CLI depth for the duration of the current scope.
Definition cli.h:56
#define SELF_PTR(ptr)
Macro to get a pointer to a percpu variable on the current CPU.
Definition percpu.h:93
#define SELF
Macro to access data in the current cpu.
Definition percpu.h:85
#define PERCPU_DEFINE_CTOR(type, name)
Macro to define a percpu variable with a constructor.
Definition percpu.h:130
uint64_t rdrand_do(uint32_t *value, uint8_t retries)
Generates a random 32-bit unsigned integer using the RDRAND instruction.
uint64_t rand_gen(void *buffer, uint64_t size)
Fills a buffer with random bytes.
Definition rand.c:64
#define LOG_WARN(format,...)
Definition log.h:92
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
Definition clock.c:99
static void cpuid_feature_info(cpuid_feature_info_t *info)
Wrapper to get CPU feature information.
Definition cpuid.h:205
@ CPUID_ECX_RDRAND
Definition cpuid.h:77
#define ERR
Integer error value.
Definition ERR.h:17
static uint64_t rand_gen_fallback(void *buffer, uint64_t size)
Definition rand.c:14
static atomic_uint64_t seed
Definition rand.c:12
#define atomic_store(object, desired)
Definition stdatomic.h:289
#define atomic_load(object)
Definition stdatomic.h:288
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
#define UINT64_MAX
Definition stdint.h:74
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
CPU feature information structure.
Definition cpuid.h:193
cpuid_ecx_features_t featuresEcx
Definition cpuid.h:196
CPU random number generator context.
Definition rand.h:23
bool rdrandAvail
If set, the RDRAND instruction is available and working.
Definition rand.h:24