diff options
-rw-r--r-- | board/host/board.c | 17 | ||||
-rw-r--r-- | test/build.mk | 1 | ||||
-rw-r--r-- | test/entropy.c | 48 |
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(); } |