Add a more proper rand implementation
diff --git a/qloader2.bin b/qloader2.bin
index 5fbeffb7..dc477f15 100644
Binary files a/qloader2.bin and b/qloader2.bin differ
diff --git a/src/lib/rand.c b/src/lib/rand.c
new file mode 100644
index 00000000..ff3550ef
--- /dev/null
+++ b/src/lib/rand.c
@@ -0,0 +1,101 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <lib/blib.h>
+#include <lib/print.h>
+#include <lib/rand.h>
+
+// TODO: Find where this mersenne twister implementation is inspired from
+// and properly credit the original author(s).
+
+#define rdrand(type) ({ \
+ type ret; \
+ asm volatile ( \
+ "1: " \
+ "rdrand %0;" \
+ "jnc 1b;" \
+ : "=r" (ret) \
+ ); \
+ ret; \
+})
+
+#define rdtsc(type) ({ \
+ type ret; \
+ asm volatile ( \
+ "rdtsc;" \
+ : "=A" (ret) \
+ ); \
+ ret; \
+})
+
+static bool rdrand_available = false;
+
+void init_rand(void) {
+ {
+ uint32_t eax, ebx, ecx, edx;
+ int ret = cpuid(1, 0, &eax, &ebx, &ecx, &edx);
+
+ if (!ret && (ecx & (1 << 30)))
+ rdrand_available = true;
+ }
+
+ uint32_t seed = ((uint32_t)0xc597060c * rdtsc(uint32_t))
+ * ((uint32_t)0xce86d624)
+ ^ ((uint32_t)0xee0da130 * rdtsc(uint32_t));
+
+ if (!rdrand_available) {
+ srand(seed);
+ } else {
+ seed *= (seed ^ rdrand(uint32_t));
+ srand(seed);
+ }
+}
+
+#define n ((int)624)
+#define m ((int)397)
+#define matrix_a ((uint32_t)0x9908b0df)
+#define msb ((uint32_t)0x80000000)
+#define lsbs ((uint32_t)0x7fffffff)
+
+static uint32_t status[n];
+static int ctr;
+
+void srand(uint32_t s) {
+ status[0] = s;
+ for (ctr = 1; ctr < n; ctr++)
+ status[ctr] = (1812433253 * (status[ctr - 1] ^ (status[ctr - 1] >> 30)) + ctr);
+}
+
+uint32_t rand32(void) {
+ const uint32_t mag01[2] = {0, matrix_a};
+
+ if (ctr >= n) {
+ for (int kk = 0; kk < n - m; kk++) {
+ uint32_t y = (status[kk] & msb) | (status[kk + 1] & lsbs);
+ status[kk] = status[kk + m] ^ (y >> 1) ^ mag01[y & 1];
+ }
+
+ for (int kk = n - m; kk < n - 1; kk++) {
+ uint32_t y = (status[kk] & msb) | (status[kk + 1] & lsbs);
+ status[kk] = status[kk + (m - n)] ^ (y >> 1) ^ mag01[y & 1];
+ }
+
+ uint32_t y = (status[n - 1] & msb) | (status[0] & lsbs);
+ status[n - 1] = status[m - 1] ^ (y >> 1) ^ mag01[y & 1];
+
+ ctr = 0;
+ }
+
+ uint32_t res = status[ctr++];
+
+ res ^= (res >> 11);
+ res ^= (res << 7) & 0x9d2c5680;
+ res ^= (res << 15) & 0xefc60000;
+ res ^= (res >> 18);
+
+ return res;
+}
+
+uint64_t rand64(void) {
+ return (((uint64_t)rand32()) << 32) | (uint64_t)rand32();
+}
diff --git a/src/lib/rand.h b/src/lib/rand.h
new file mode 100644
index 00000000..0a2f88a3
--- /dev/null
+++ b/src/lib/rand.h
@@ -0,0 +1,13 @@
+#ifndef __LIB__RAND_H__
+#define __LIB__RAND_H__
+
+#include <stdint.h>
+
+void init_rand(void);
+
+void srand(uint32_t s);
+
+uint32_t rand32(void);
+uint64_t rand64(void);
+
+#endif
diff --git a/src/lib/random.c b/src/lib/random.c
deleted file mode 100644
index dccb2656..00000000
--- a/src/lib/random.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <lib/blib.h>
-
-int rdrand_available = 0;
-
-static void check_rdrand(void) {
- uint32_t eax, ebx, ecx, edx;
- int ret = cpuid(1, 0, &eax, &ebx, &ecx, &edx);
- if (ret)
- return;
-
- if (ecx & (1 << 30))
- rdrand_available = 1;
-}
-
-static void init_simple_rand(void) {
- // TODO: Some fallback randomness init
-}
-
-void init_random(void) {
- check_rdrand();
- if (!rdrand_available) {
- init_simple_rand();
- }
-}
-
-static uint32_t rdrand(void) {
- uint32_t val;
-
- asm (
- "1:rdrand %0\n\t"
- "jnc 1b\n\t"
- :"=r"(val)
- );
-
- return val;
-}
-
-static uint32_t simple_rand(void) {
- // TODO: Some fallback randomness
- return 0xFEEDFACE;
-}
-
-uint32_t get_random(void) {
- if (rdrand_available)
- return rdrand();
- else
- return simple_rand();
-}
diff --git a/src/lib/random.h b/src/lib/random.h
deleted file mode 100644
index 45a788b6..00000000
--- a/src/lib/random.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __LIB__RANDOM_H__
-#define __LIB__RANDOM_H__
-
-#include <stdint.h>
-
-void init_random(void);
-
-uint32_t get_random(void);
-
-#endif
diff --git a/src/main.c b/src/main.c
index 18c2f8d6..725e0f19 100644
--- a/src/main.c
+++ b/src/main.c
@@ -22,7 +22,7 @@ asm (
#include <lib/config.h>
#include <lib/e820.h>
#include <lib/print.h>
-#include <lib/random.h>
+#include <lib/rand.h>
#include <fs/file.h>
#include <lib/elf.h>
#include <protos/stivale.h>
@@ -99,7 +99,7 @@ refresh:
void main(int boot_drive) {
// Initial prompt.
init_vga_textmode();
- init_random();
+ init_rand();
print("qloader2\n\n");
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 59a0c4e2..30efd465 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -9,7 +9,7 @@
#include <lib/config.h>
#include <lib/time.h>
#include <lib/print.h>
-#include <lib/random.h>
+#include <lib/rand.h>
#include <lib/real.h>
#include <drivers/vbe.h>
#include <drivers/vga_textmode.h>
@@ -110,7 +110,7 @@ void stivale_load(char *cmdline, int boot_drive) {
if (!ret && ((stivale_hdr.flags >> 2) & 1)) {
// KASLR is enabled, set the slide
- slide = get_random() & KASLR_SLIDE_BITMASK;
+ slide = rand64() & KASLR_SLIDE_BITMASK;
// Re-read the .stivalehdr with slid relocations
ret = elf64_load_section(fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide);
