On Tue, 25 Oct 2022 at 01:44, Jason A. Donenfeld <ja...@zx2c4.com> wrote: > > As of the kernel commit linked below, Linux ingests an RNG seed > passed as part of the environment block by the bootloader or firmware. > This mechanism works across all different environment block types, > generically, which pass some block via the second firmware argument. On > malta, this has been tested to work when passed as an argument from > U-Boot's linux_env_set. > > As is the case on most other architectures (such as boston), when > booting with `-kernel`, QEMU, acting as the bootloader, should pass the > RNG seed, so that the machine has good entropy for Linux to consume. So > this commit implements that quite simply by using the guest random API, > which is what is used on nearly all other archs too. It also > reinitializes the seed on reboot, so that it is always fresh. > > Link: https://git.kernel.org/torvalds/c/056a68cea01 > Cc: Aleksandar Rikalo <aleksandar.rik...@syrmia.com> > Cc: Paul Burton <paulbur...@kernel.org> > Cc: Philippe Mathieu-Daudé <f4...@amsat.org> > Signed-off-by: Jason A. Donenfeld <ja...@zx2c4.com> > --- > hw/mips/malta.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/hw/mips/malta.c b/hw/mips/malta.c > index 0e932988e0..d337de920c 100644 > --- a/hw/mips/malta.c > +++ b/hw/mips/malta.c > @@ -26,6 +26,7 @@ > #include "qemu/units.h" > #include "qemu/bitops.h" > #include "qemu/datadir.h" > +#include "qemu/guest-random.h" > #include "hw/clock.h" > #include "hw/southbridge/piix.h" > #include "hw/isa/superio.h" > @@ -1017,6 +1018,17 @@ static void G_GNUC_PRINTF(3, 4) prom_set(uint32_t > *prom_buf, int index, > va_end(ap); > } > > +static void reinitialize_rng_seed(void *opaque) > +{ > + char *rng_seed_hex = opaque; > + uint8_t rng_seed[32]; > + > + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); > + for (size_t i = 0; i < sizeof(rng_seed); ++i) { > + sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]); > + } > +} > + > /* Kernel */ > static uint64_t load_kernel(void) > { > @@ -1028,6 +1040,8 @@ static uint64_t load_kernel(void) > long prom_size; > int prom_index = 0; > uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr); > + uint8_t rng_seed[32]; > + char rng_seed_hex[sizeof(rng_seed) * 2 + 1]; > > #if TARGET_BIG_ENDIAN > big_endian = 1; > @@ -1115,9 +1129,20 @@ static uint64_t load_kernel(void) > > prom_set(prom_buf, prom_index++, "modetty0"); > prom_set(prom_buf, prom_index++, "38400n8r"); > + > + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); > + for (size_t i = 0; i < sizeof(rng_seed); ++i) { > + sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]); > + } > + prom_set(prom_buf, prom_index++, "rngseed"); > + prom_set(prom_buf, prom_index++, "%s", rng_seed_hex); > + > prom_set(prom_buf, prom_index++, NULL); > > rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR); > + qemu_register_reset_nosnapshotload(reinitialize_rng_seed, > + memmem(rom_ptr(ENVP_PADDR, prom_size), prom_size, > + rng_seed_hex, sizeof(rng_seed_hex)));
So I didn't take this one patch, partly because I don't think all our supported build platforms have memmem(), and partly because when I then looked a bit closer at it it looks like we're searching through the whole blob for the RNG seed. We know where it is to start with, so I think it would be cleaner to have prom_set return table_addr (ie the offset into the blob of what it just wrote) so we can use it here. (You could also reverse-engineer it from prom_buf[prom_index - 1] but returning the offset seems a bit less awkward.) thanks -- PMM