summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/host/board.c17
-rw-r--r--test/build.mk1
-rw-r--r--test/entropy.c48
3 files changed, 58 insertions, 8 deletions
diff --git a/board/host/board.c b/board/host/board.c
index 408bfdcf0b..b29f6e9230 100644
--- a/board/host/board.c
+++ b/board/host/board.c
@@ -67,3 +67,20 @@ const struct i2c_port_t i2c_ports[] = {
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
#endif
+
+#ifdef TEST_BUILD
+/* Poor source of entropy for testing purpose. */
+int board_get_entropy(void *buffer, int len)
+{
+ static uint32_t seed = 0xcafecafe;
+ int i = 0;
+ uint8_t *data = buffer;
+
+ for (i = 0; i < len; i++) {
+ seed *= 7;
+ data[i] = seed + (seed >> 24);
+ }
+
+ return 1;
+}
+#endif
diff --git a/test/build.mk b/test/build.mk
index 807d0f57b7..6081a7d785 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -45,6 +45,7 @@ test-list-host += charge_manager
test-list-host += charge_manager_drp_charging
test-list-host += charge_ramp
test-list-host += console_edit
+test-list-host += entropy
test-list-host += extpwr_gpio
test-list-host += fan
test-list-host += flash
diff --git a/test/entropy.c b/test/entropy.c
index f01a3dd0a0..7498d4edf9 100644
--- a/test/entropy.c
+++ b/test/entropy.c
@@ -15,6 +15,20 @@
static int buckets[256];
+static const int log2_mult = 2;
+
+/*
+ * log2 (multiplied by 2). For non-power of 2, this rounds to the closest
+ * half-integer, otherwise the value is exact.
+ */
+uint32_t log2(int32_t val)
+{
+ int val1 = 31 - __builtin_clz(val);
+ int val2 = 32 - __builtin_clz(val - 1);
+
+ return log2_mult * (val1 + val2)/2;
+}
+
void run_test(void)
{
const int loopcount = 512;
@@ -22,6 +36,9 @@ void run_test(void)
uint8_t buffer[32];
timestamp_t t0, t1;
int i, j;
+ uint32_t entropy;
+ const int totalcount = loopcount * sizeof(buffer);
+ const int log2totalcount = log2(totalcount);
memset(buckets, 0, sizeof(buckets));
@@ -43,18 +60,33 @@ void run_test(void)
watchdog_reload();
}
- ccprintf("Total count: %d\n", loopcount * sizeof(buffer));
+ ccprintf("Total count: %d\n", totalcount);
ccprintf("Buckets: ");
+ entropy = 0;
for (j = 0; j < 256; j++) {
+ /*
+ * Shannon entropy (base 2) is sum of -p[j] * log_2(p[j]).
+ * p[j] = buckets[j]/totalcount
+ * -p[j] * log_2(p[j])
+ * = -(buckets[j]/totalcount) * log_2(buckets[j]/totalcount)
+ * = buckets[j] * (log_2(totalcount) - log_2(buckets[j]))
+ * / totalcount
+ * Our log2() function is scaled by log2_mult, and we defer the
+ * division by totalcount until we get the total sum, so we need
+ * to divide by (log2_mult * totalcount) at the end.
+ */
+ entropy += buckets[j] * (log2totalcount - log2(buckets[j]));
ccprintf("%d;", buckets[j]);
cflush();
}
ccprintf("\n");
- /*
- * From the data above, entropy can be obtained with this command:
- * tr ';' '\n' | awk 'BEGIN { e = 0; tot=16384.0 }
- { p = $1/tot; if (p > 0) { e -= p*log(p)/log(2) } }
- END { print e }'
- */
- test_pass();
+
+ ccprintf("Entropy: %u/1000 bits\n",
+ entropy * 1000 / (log2_mult * totalcount));
+
+ /* We want at least 2 bits of entropy (out of a maximum of 8) */
+ if ((entropy / (log2_mult * totalcount)) >= 2)
+ test_pass();
+ else
+ test_fail();
}