[vim2] fix issues with passing entropy to zircon. This CL fixes a bunch of small issues that surfaced when we tried to port this change to a different board. Changes: * Sort includes in alphabetical order. * Remove magic constant specifying the size of the kernel entropy cmdline string. * Fix error in the static_assert checking bounds of the CMDLINE_ENTROPY_SIZE (each char would produce 4 bits of entropy instead of 8) * Add static_assert checking that CMDLINE_ENTROPY_BITS is multiple of 32, to avoid writing more than we request. * Separate the hw_rand_hex into a function that only reads the hw rng and another that converts an uint32 into a 8 hex chars. * Fix a typo that avoided adding a '\0' at the end of the cmdline string. * Add a mandatory_memset implementation, and call that instead of memset for clearing the cmdline buffer after adding the zbi cmdline. TEST=flashed into a vim2 and checked that zircon received the entropy. Manually verified that the static asserts have the right bounds. Change-Id: I93a33c48d201572be3a6603c11b381a297459eb0
diff --git a/board/khadas/kvim2/zircon.c b/board/khadas/kvim2/zircon.c index 00a249d..7f86a9f 100644 --- a/board/khadas/kvim2/zircon.c +++ b/board/khadas/kvim2/zircon.c
@@ -4,11 +4,11 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <aml_i2c.h> +#include <asm/arch/secure_apb.h> #include <common.h> #include <part.h> #include <zircon/zircon.h> -#include <asm/arch/secure_apb.h> -#include <aml_i2c.h> #define PDEV_VID_KHADAS 4 #define PDEV_PID_VIM2 2 @@ -17,13 +17,22 @@ #define CMDLINE_ENTROPY_SIZE 1024 #define CMDLINE_ENTROPY_BITS 256 // random bits to pass to zircon. + +#define ENTROPY_BITS_PER_CHAR 4 + +static char entropy_cmdline[CMDLINE_ENTROPY_SIZE] = {0}; +static const char zircon_entropy_arg[] = "kernel.entropy-mixin="; + #define static_assert _Static_assert -static_assert((CMDLINE_ENTROPY_BITS/8) + 22 < CMDLINE_ENTROPY_SIZE, +static_assert(CMDLINE_ENTROPY_BITS % 32 == 0, + "Requested entropy must be a multiple of 32"); + +static_assert((CMDLINE_ENTROPY_BITS/ENTROPY_BITS_PER_CHAR) \ + + sizeof(zircon_entropy_arg) < CMDLINE_ENTROPY_SIZE, "Requested entropy doesn't fit in cmdline."); -static const char BOOTLOADER_VERSION[] = "zircon-bootloader=0.11"; +static const char BOOTLOADER_VERSION[] = "zircon-bootloader=0.12"; -static char entropy_cmdline[CMDLINE_ENTROPY_SIZE] = "kernel.entropy-mixin="; static const zbi_cpu_config_t cpu_config = { .cluster_count = 2, @@ -187,6 +196,16 @@ }, }; +static void* mandatory_memset(void* dst, int c, size_t n) { + volatile unsigned char* out = dst; + size_t i = 0; + + for (i = 0; i < n; ++i) { + out[i] = (unsigned char)c; + } + return dst; +} + static void add_partition_map(zbi_header_t* zbi) { block_dev_desc_t* dev_desc; disk_partition_t bootloader_info; @@ -314,32 +333,40 @@ printf("MAC address parsing failed for \"%s\"\n", getenv("eth_mac")); } -// fills an 8 char buffer with random hex digits, drawn from the -// hardware cprng. +// fills an 8 char buffer with the lowercase hex representation of the given +// value. // WARNING this does not add a '\0' to the end of the buffer. -static inline void hw_rand_hex(char buf[static 8]) { - static const char* hex = "0123456789abcdef"; +static inline void uint32_to_hex(uint32_t val, char buf[static 8]) { + static const char hex[] = "0123456789abcdef"; + int i = 0; - uint32_t rnd = readl(P_RAND64_ADDR0); - int i; - for (i = 0; i < 8; ++i) { - buf[i] = hex[rnd & 0xF]; - rnd >>= 4; + for (i = 7; i >= 0; i--) { + buf[i] = hex[val & 0xF]; + val >>= 4; } } -static void add_cmdline_entropy(zbi_header_t* zbi) { - char *entropy = entropy_cmdline + strlen(entropy_cmdline); +// Reads a value from the userspace hardware random number generator. +// NOTE that there is no guarantee of the quality of this rng. +static inline uint32_t read_hw_rng(void) { + return readl(P_RAND64_ADDR0); +} - int i; +static void add_cmdline_entropy(zbi_header_t* zbi) { + strcpy(entropy_cmdline, zircon_entropy_arg); + char *entropy = entropy_cmdline + strlen(zircon_entropy_arg); + int i = 0; + for (i = 0; i < CMDLINE_ENTROPY_BITS; i += 32) { - hw_rand_hex(entropy); + uint32_to_hex(read_hw_rng(), entropy); entropy += 8; } - entropy = '\0'; + *entropy = '\0'; - zircon_append_boot_item(zbi, ZBI_TYPE_CMDLINE, 0, entropy_cmdline, CMDLINE_ENTROPY_SIZE); - memset(entropy_cmdline, '\0', CMDLINE_ENTROPY_SIZE); + zircon_append_boot_item(zbi, ZBI_TYPE_CMDLINE, 0, entropy_cmdline, + sizeof(entropy_cmdline)); + + mandatory_memset(entropy_cmdline, '\0', sizeof(entropy_cmdline)); } int zircon_preboot(zbi_header_t* zbi) {