Module Name: src Committed By: rin Date: Mon Jul 10 07:00:12 UTC 2023
Modified Files: src/sys/arch/aarch64/aarch64: efi_machdep.c src/sys/arch/arm/arm: efi_machdep.c efi_runtime.h src/sys/arch/evbarm/fdt: fdt_machdep.c src/sys/dev/fdt: fdt_boot.c fdt_boot.h Added Files: src/sys/arch/arm/include: efirt.h src/sys/arch/evbarm/include: efirt.h Log Message: Factor out some fdt(4) features from {,evb}arm into dev/fdt. Now, FDT-based support to efirt, initrd, rndseed, and efirng can be used from, e.g., riscv. Mostly from Nick Hudson. XXX As Nick comments, there can be some optimizations for fdt_map_range(). efiboot may also be modified to load these objects into aligned PAs. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/arch/aarch64/aarch64/efi_machdep.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/arm/efi_machdep.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/arm/efi_runtime.h cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/include/efirt.h cvs rdiff -u -r1.103 -r1.104 src/sys/arch/evbarm/fdt/fdt_machdep.c cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/include/efirt.h cvs rdiff -u -r1.1 -r1.2 src/sys/dev/fdt/fdt_boot.c \ src/sys/dev/fdt/fdt_boot.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/aarch64/aarch64/efi_machdep.c diff -u src/sys/arch/aarch64/aarch64/efi_machdep.c:1.13 src/sys/arch/aarch64/aarch64/efi_machdep.c:1.14 --- src/sys/arch/aarch64/aarch64/efi_machdep.c:1.13 Tue May 3 20:10:20 2022 +++ src/sys/arch/aarch64/aarch64/efi_machdep.c Mon Jul 10 07:00:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_machdep.c,v 1.13 2022/05/03 20:10:20 skrll Exp $ */ +/* $NetBSD: efi_machdep.c,v 1.14 2023/07/10 07:00:11 rin Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,12 +30,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.13 2022/05/03 20:10:20 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.14 2023/07/10 07:00:11 rin Exp $"); #include <sys/param.h> + #include <uvm/uvm_extern.h> #include <arm/cpufunc.h> +#include <arm/efirt.h> #include <arm/arm/efi_runtime.h> @@ -49,8 +51,8 @@ static struct { static bool efi_userva = true; void -arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz, - enum arm_efirt_mem_type type) +cpu_efirt_map_range(vaddr_t va, paddr_t pa, size_t sz, + enum cpu_efirt_mem_type type) { int flags = 0; int prot = 0; Index: src/sys/arch/arm/arm/efi_machdep.c diff -u src/sys/arch/arm/arm/efi_machdep.c:1.3 src/sys/arch/arm/arm/efi_machdep.c:1.4 --- src/sys/arch/arm/arm/efi_machdep.c:1.3 Sun Dec 18 12:02:46 2022 +++ src/sys/arch/arm/arm/efi_machdep.c Mon Jul 10 07:00:12 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_machdep.c,v 1.3 2022/12/18 12:02:46 skrll Exp $ */ +/* $NetBSD: efi_machdep.c,v 1.4 2023/07/10 07:00:12 rin Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,11 +30,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.3 2022/12/18 12:02:46 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.4 2023/07/10 07:00:12 rin Exp $"); #include <sys/param.h> + #include <uvm/uvm_extern.h> +#include <arm/efirt.h> #include <arm/vfpreg.h> #include <arm/arm/efi_runtime.h> @@ -101,8 +103,8 @@ arm_efirt_md_exit(void) void -arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz, - enum arm_efirt_mem_type type) +cpu_efirt_map_range(vaddr_t va, paddr_t pa, size_t sz, + enum cpu_efirt_mem_type type) { int flags = 0; int prot = 0; Index: src/sys/arch/arm/arm/efi_runtime.h diff -u src/sys/arch/arm/arm/efi_runtime.h:1.4 src/sys/arch/arm/arm/efi_runtime.h:1.5 --- src/sys/arch/arm/arm/efi_runtime.h:1.4 Sun Oct 10 13:03:09 2021 +++ src/sys/arch/arm/arm/efi_runtime.h Mon Jul 10 07:00:12 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_runtime.h,v 1.4 2021/10/10 13:03:09 jmcneill Exp $ */ +/* $NetBSD: efi_runtime.h,v 1.5 2023/07/10 07:00:12 rin Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -44,13 +44,6 @@ efi_status arm_efirt_setvar(uint16_t *, u_long, void *); int arm_efirt_reset(enum efi_reset); -enum arm_efirt_mem_type { - ARM_EFIRT_MEM_CODE, - ARM_EFIRT_MEM_DATA, - ARM_EFIRT_MEM_MMIO, -}; - -void arm_efirt_md_map_range(vaddr_t, paddr_t, size_t, enum arm_efirt_mem_type); int arm_efirt_md_enter(void); void arm_efirt_md_exit(void); Index: src/sys/arch/evbarm/fdt/fdt_machdep.c diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.103 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.104 --- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.103 Sat Apr 22 09:53:45 2023 +++ src/sys/arch/evbarm/fdt/fdt_machdep.c Mon Jul 10 07:00:12 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_machdep.c,v 1.103 2023/04/22 09:53:45 skrll Exp $ */ +/* $NetBSD: fdt_machdep.c,v 1.104 2023/07/10 07:00:12 rin Exp $ */ /*- * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.103 2023/04/22 09:53:45 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.104 2023/07/10 07:00:12 rin Exp $"); #include "opt_arm_debug.h" #include "opt_bootconfig.h" @@ -35,7 +35,6 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep. #include "opt_ddb.h" #include "opt_efi.h" #include "opt_machdep.h" -#include "opt_md.h" #include "opt_multiprocessor.h" #include "genfb.h" @@ -65,8 +64,6 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep. #include <sys/proc.h> #include <sys/pserialize.h> #include <sys/reboot.h> -#include <sys/rnd.h> -#include <sys/rndsource.h> #include <sys/systm.h> #include <sys/termios.h> #include <sys/vnode.h> @@ -113,10 +110,6 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep. #include <dev/wscons/wsdisplayvar.h> #endif -#ifdef MEMORY_DISK_DYNAMIC -#include <dev/md.h> -#endif - #ifndef FDT_MAX_BOOT_STRING #define FDT_MAX_BOOT_STRING 1024 #endif @@ -129,10 +122,6 @@ char *boot_args = NULL; u_long uboot_args[4] __attribute__((__section__(".data"))); const uint8_t *fdt_addr_r __attribute__((__section__(".data"))); -static uint64_t initrd_start, initrd_end; -static uint64_t rndseed_start, rndseed_end; /* our on-disk seed */ -static uint64_t efirng_start, efirng_end; /* firmware's EFI RNG output */ - #include <libfdt.h> #include <dev/fdt/fdtvar.h> #define FDT_BUF_SIZE (512*1024) @@ -241,21 +230,10 @@ fdt_build_bootconfig(uint64_t mem_start, uint64_t addr, size; int index; - const uint64_t initrd_size = - round_page(initrd_end) - trunc_page(initrd_start); - if (initrd_size > 0) - fdt_memory_remove_range(trunc_page(initrd_start), initrd_size); - - const uint64_t rndseed_size = - round_page(rndseed_end) - trunc_page(rndseed_start); - if (rndseed_size > 0) - fdt_memory_remove_range(trunc_page(rndseed_start), - rndseed_size); - - const uint64_t efirng_size = - round_page(efirng_end) - trunc_page(efirng_start); - if (efirng_size > 0) - fdt_memory_remove_range(trunc_page(efirng_start), efirng_size); + /* Reserve pages for ramdisk, rndseed, and firmware's RNG */ + fdt_reserve_initrd(); + fdt_reserve_rndseed(); + fdt_reserve_efirng(); const int framebuffer = OF_finddevice("/chosen/framebuffer"); if (framebuffer >= 0) { @@ -271,222 +249,6 @@ fdt_build_bootconfig(uint64_t mem_start, fdt_memory_foreach(fdt_add_dram_blocks, bc); } -static void -fdt_probe_range(const char *startname, const char *endname, - uint64_t *pstart, uint64_t *pend) -{ - int chosen, len; - const void *start_data, *end_data; - - *pstart = *pend = 0; - - chosen = OF_finddevice("/chosen"); - if (chosen < 0) - return; - - start_data = fdtbus_get_prop(chosen, startname, &len); - end_data = fdtbus_get_prop(chosen, endname, NULL); - if (start_data == NULL || end_data == NULL) - return; - - switch (len) { - case 4: - *pstart = be32dec(start_data); - *pend = be32dec(end_data); - break; - case 8: - *pstart = be64dec(start_data); - *pend = be64dec(end_data); - break; - default: - printf("Unsupported len %d for /chosen `%s'\n", - len, startname); - return; - } -} - -static void * -fdt_map_range(uint64_t start, uint64_t end, uint64_t *psize, - const char *purpose) -{ - const paddr_t startpa = trunc_page(start); - const paddr_t endpa = round_page(end); - paddr_t pa; - vaddr_t va; - void *ptr; - - *psize = end - start; - if (*psize == 0) - return NULL; - - const vaddr_t voff = start & PAGE_MASK; - - va = uvm_km_alloc(kernel_map, *psize, 0, UVM_KMF_VAONLY | UVM_KMF_NOWAIT); - if (va == 0) { - printf("Failed to allocate VA for %s\n", purpose); - return NULL; - } - ptr = (void *)(va + voff); - - for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) - pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0); - pmap_update(pmap_kernel()); - - return ptr; -} - -static void -fdt_unmap_range(void *ptr, uint64_t size) -{ - const char *start = ptr, *end = start + size; - const vaddr_t startva = trunc_page((vaddr_t)(uintptr_t)start); - const vaddr_t endva = round_page((vaddr_t)(uintptr_t)end); - const vsize_t sz = endva - startva; - - pmap_kremove(startva, sz); - pmap_update(pmap_kernel()); - - uvm_km_free(kernel_map, startva, sz, UVM_KMF_VAONLY); -} - -static void -fdt_probe_initrd(uint64_t *pstart, uint64_t *pend) -{ - *pstart = *pend = 0; - -#ifdef MEMORY_DISK_DYNAMIC - fdt_probe_range("linux,initrd-start", "linux,initrd-end", pstart, pend); -#endif -} - -static void -fdt_setup_initrd(void) -{ -#ifdef MEMORY_DISK_DYNAMIC - void *md_start; - uint64_t initrd_size; - - md_start = fdt_map_range(initrd_start, initrd_end, &initrd_size, - "initrd"); - if (md_start == NULL) - return; - md_root_setconf(md_start, initrd_size); -#endif -} - -static void -fdt_probe_rndseed(uint64_t *pstart, uint64_t *pend) -{ - - fdt_probe_range("netbsd,rndseed-start", "netbsd,rndseed-end", - pstart, pend); -} - -static void -fdt_setup_rndseed(void) -{ - uint64_t rndseed_size; - void *rndseed; - - rndseed = fdt_map_range(rndseed_start, rndseed_end, &rndseed_size, - "rndseed"); - if (rndseed == NULL) - return; - rnd_seed(rndseed, rndseed_size); - fdt_unmap_range(rndseed, rndseed_size); -} - -static void -fdt_probe_efirng(uint64_t *pstart, uint64_t *pend) -{ - - fdt_probe_range("netbsd,efirng-start", "netbsd,efirng-end", - pstart, pend); -} - -static struct krndsource efirng_source; - -static void -fdt_setup_efirng(void) -{ - uint64_t efirng_size; - void *efirng; - - efirng = fdt_map_range(efirng_start, efirng_end, &efirng_size, - "efirng"); - if (efirng == NULL) - return; - - rnd_attach_source(&efirng_source, "efirng", RND_TYPE_RNG, - RND_FLAG_DEFAULT); - - /* - * We don't really have specific information about the physical - * process underlying the data provided by the firmware via the - * EFI RNG API, so the entropy estimate here is heuristic. - * What efiboot provides us is up to 4096 bytes of data from - * the EFI RNG API, although in principle it may return short. - * - * The UEFI Specification (2.8 Errata A, February 2020[1]) says - * - * When a Deterministic Random Bit Generator (DRBG) is - * used on the output of a (raw) entropy source, its - * security level must be at least 256 bits. - * - * It's not entirely clear whether `it' refers to the DRBG or - * the entropy source; if it refers to the DRBG, it's not - * entirely clear how ANSI X9.31 3DES, one of the options for - * DRBG in the UEFI spec, can provide a `256-bit security - * level' because it has only 232 bits of inputs (three 56-bit - * keys and one 64-bit block). That said, even if it provides - * only 232 bits of entropy, that's enough to prevent all - * attacks and we probably get a few more bits from sampling - * the clock anyway. - * - * In the event we get raw samples, e.g. the bits sampled by a - * ring oscillator, we hope that the samples have at least half - * a bit of entropy per bit of data -- and efiboot tries to - * draw 4096 bytes to provide plenty of slop. Hence we divide - * the total number of bits by two and clamp at 256. There are - * ways this could go wrong, but on most machines it should - * behave reasonably. - * - * [1] https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_A_Feb14.pdf - */ - rnd_add_data(&efirng_source, efirng, efirng_size, - MIN(256, efirng_size*NBBY/2)); - - explicit_memset(efirng, 0, efirng_size); - fdt_unmap_range(efirng, efirng_size); -} - -#ifdef EFI_RUNTIME -static void -fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type) -{ - int len; - - const int chosen_off = fdt_path_offset(fdt_data, "/chosen"); - if (chosen_off < 0) - return; - - const uint64_t *map = fdt_getprop(fdt_data, chosen_off, prop, &len); - if (map == NULL) - return; - - while (len >= 24) { - const paddr_t pa = be64toh(map[0]); - const vaddr_t va = be64toh(map[1]); - const size_t sz = be64toh(map[2]); - VPRINTF("%s: %s %#" PRIxPADDR "-%#" PRIxVADDR " (%#" PRIxVADDR - "-%#" PRIxVSIZE ")\n", __func__, prop, pa, pa + sz - 1, - va, va + sz - 1); - arm_efirt_md_map_range(va, pa, sz, type); - map += 3; - len -= 24; - } -} -#endif vaddr_t initarm(void *arg) @@ -604,11 +366,11 @@ initarm(void *arg) PRIx64 ")\n", __func__, memory_start, memory_end, memory_size); /* Parse ramdisk info */ - fdt_probe_initrd(&initrd_start, &initrd_end); + fdt_probe_initrd(); /* Parse our on-disk rndseed and the firmware's RNG from EFI */ - fdt_probe_rndseed(&rndseed_start, &rndseed_end); - fdt_probe_efirng(&efirng_start, &efirng_end); + fdt_probe_rndseed(); + fdt_probe_efirng(); fdt_memory_remove_reserved(memory_start, memory_end); Index: src/sys/dev/fdt/fdt_boot.c diff -u src/sys/dev/fdt/fdt_boot.c:1.1 src/sys/dev/fdt/fdt_boot.c:1.2 --- src/sys/dev/fdt/fdt_boot.c:1.1 Sat Apr 22 09:53:45 2023 +++ src/sys/dev/fdt/fdt_boot.c Mon Jul 10 07:00:12 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_boot.c,v 1.1 2023/04/22 09:53:45 skrll Exp $ */ +/* $NetBSD: fdt_boot.c,v 1.2 2023/07/10 07:00:12 rin Exp $ */ /*- * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca> @@ -56,16 +56,307 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdt_boot.c,v 1.1 2023/04/22 09:53:45 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_boot.c,v 1.2 2023/07/10 07:00:12 rin Exp $"); + +#include "opt_efi.h" +#include "opt_md.h" #include <sys/param.h> +#include <sys/disk.h> +#include <sys/disklabel.h> +#include <sys/fcntl.h> +#include <sys/md5.h> #include <sys/optstr.h> +#include <sys/rnd.h> +#include <sys/rndsource.h> +#include <sys/uuid.h> +#include <sys/vnode.h> + +#include <net/if.h> +#include <net/if_dl.h> + +#include <uvm/uvm_extern.h> #include <libfdt.h> #include <dev/fdt/fdtvar.h> #include <dev/fdt/fdt_boot.h> +#if 0 +#include <dev/fdt/fdt_ddb.h> +#endif +#include <dev/fdt/fdt_memory.h> + +#ifdef EFI_RUNTIME +#include <machine/efirt.h> + +void fdt_map_efi_runtime(const char *, enum cpu_efirt_mem_type); + +#endif + +#ifdef MEMORY_DISK_DYNAMIC +#include <dev/md.h> + +static uint64_t initrd_start, initrd_end; +#endif + +static uint64_t rndseed_start, rndseed_end; /* our on-disk seed */ +static uint64_t efirng_start, efirng_end; /* firmware's EFI RNG output */ +static struct krndsource efirng_source; + + +static void +fdt_probe_range(const char *startname, const char *endname, + uint64_t *pstart, uint64_t *pend) +{ + int chosen, len; + const void *start_data, *end_data; + + *pstart = *pend = 0; + + chosen = OF_finddevice("/chosen"); + if (chosen < 0) + return; + + start_data = fdtbus_get_prop(chosen, startname, &len); + end_data = fdtbus_get_prop(chosen, endname, NULL); + if (start_data == NULL || end_data == NULL) + return; + + switch (len) { + case 4: + *pstart = be32dec(start_data); + *pend = be32dec(end_data); + break; + case 8: + *pstart = be64dec(start_data); + *pend = be64dec(end_data); + break; + default: + printf("Unsupported len %d for /chosen `%s'\n", + len, startname); + return; + } +} + + +static void * +fdt_map_range(uint64_t start, uint64_t end, uint64_t *psize, + const char *purpose) +{ + const paddr_t startpa = trunc_page(start); + const paddr_t endpa = round_page(end); + paddr_t pa; + vaddr_t va; + void *ptr; + + *psize = end - start; + if (*psize == 0) + return NULL; + + const vaddr_t voff = start & PAGE_MASK; + + // XXX NH add an align so map_chunk works betterer? + va = uvm_km_alloc(kernel_map, *psize, 0, UVM_KMF_VAONLY | UVM_KMF_NOWAIT); + if (va == 0) { + printf("Failed to allocate VA for %s\n", purpose); + return NULL; + } + ptr = (void *)(va + voff); + + // XXX NH map chunk + for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) + pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0); + pmap_update(pmap_kernel()); + + return ptr; +} + +static void +fdt_unmap_range(void *ptr, uint64_t size) +{ + const char *start = ptr, *end = start + size; + const vaddr_t startva = trunc_page((vaddr_t)(uintptr_t)start); + const vaddr_t endva = round_page((vaddr_t)(uintptr_t)end); + const vsize_t sz = endva - startva; + + pmap_kremove(startva, sz); + pmap_update(pmap_kernel()); + + uvm_km_free(kernel_map, startva, sz, UVM_KMF_VAONLY); +} + +void +fdt_probe_initrd(void) +{ + +#ifdef MEMORY_DISK_DYNAMIC + fdt_probe_range("linux,initrd-start", "linux,initrd-end", + &initrd_start, &initrd_end); +#endif +} + +void +fdt_setup_initrd(void) +{ +#ifdef MEMORY_DISK_DYNAMIC + void *md_start; + uint64_t initrd_size; + + md_start = fdt_map_range(initrd_start, initrd_end, &initrd_size, + "initrd"); + if (md_start == NULL) + return; + md_root_setconf(md_start, initrd_size); +#endif +} + +void +fdt_reserve_initrd(void) +{ +#ifdef MEMORY_DISK_DYNAMIC + const uint64_t initrd_size = + round_page(initrd_end) - trunc_page(initrd_start); + + if (initrd_size > 0) + fdt_memory_remove_range(trunc_page(initrd_start), initrd_size); +#endif +} + +void +fdt_probe_rndseed(void) +{ + + fdt_probe_range("netbsd,rndseed-start", "netbsd,rndseed-end", + &rndseed_start, &rndseed_end); +} + +void +fdt_setup_rndseed(void) +{ + uint64_t rndseed_size; + void *rndseed; + + rndseed = fdt_map_range(rndseed_start, rndseed_end, &rndseed_size, + "rndseed"); + if (rndseed == NULL) + return; + rnd_seed(rndseed, rndseed_size); + fdt_unmap_range(rndseed, rndseed_size); +} + +void +fdt_reserve_rndseed(void) +{ + const uint64_t rndseed_size = + round_page(rndseed_end) - trunc_page(rndseed_start); + + if (rndseed_size > 0) + fdt_memory_remove_range(trunc_page(rndseed_start), + rndseed_size); +} + +void +fdt_probe_efirng(void) +{ + + fdt_probe_range("netbsd,efirng-start", "netbsd,efirng-end", + &efirng_start, &efirng_end); +} + +void +fdt_setup_efirng(void) +{ + uint64_t efirng_size; + void *efirng; + + efirng = fdt_map_range(efirng_start, efirng_end, &efirng_size, + "efirng"); + if (efirng == NULL) + return; + + rnd_attach_source(&efirng_source, "efirng", RND_TYPE_RNG, + RND_FLAG_DEFAULT); + + /* + * We don't really have specific information about the physical + * process underlying the data provided by the firmware via the + * EFI RNG API, so the entropy estimate here is heuristic. + * What efiboot provides us is up to 4096 bytes of data from + * the EFI RNG API, although in principle it may return short. + * + * The UEFI Specification (2.8 Errata A, February 2020[1]) says + * + * When a Deterministic Random Bit Generator (DRBG) is + * used on the output of a (raw) entropy source, its + * security level must be at least 256 bits. + * + * It's not entirely clear whether `it' refers to the DRBG or + * the entropy source; if it refers to the DRBG, it's not + * entirely clear how ANSI X9.31 3DES, one of the options for + * DRBG in the UEFI spec, can provide a `256-bit security + * level' because it has only 232 bits of inputs (three 56-bit + * keys and one 64-bit block). That said, even if it provides + * only 232 bits of entropy, that's enough to prevent all + * attacks and we probably get a few more bits from sampling + * the clock anyway. + * + * In the event we get raw samples, e.g. the bits sampled by a + * ring oscillator, we hope that the samples have at least half + * a bit of entropy per bit of data -- and efiboot tries to + * draw 4096 bytes to provide plenty of slop. Hence we divide + * the total number of bits by two and clamp at 256. There are + * ways this could go wrong, but on most machines it should + * behave reasonably. + * + * [1] https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_A_Feb14.pdf + */ + rnd_add_data(&efirng_source, efirng, efirng_size, + MIN(256, efirng_size*NBBY/2)); + + explicit_memset(efirng, 0, efirng_size); + fdt_unmap_range(efirng, efirng_size); +} + +void +fdt_reserve_efirng(void) +{ + const uint64_t efirng_size = + round_page(efirng_end) - trunc_page(efirng_start); + + if (efirng_size > 0) + fdt_memory_remove_range(trunc_page(efirng_start), efirng_size); +} + +#ifdef EFI_RUNTIME +void +fdt_map_efi_runtime(const char *prop, enum cpu_efirt_mem_type type) +{ + int len; + + const int chosen_off = fdt_path_offset(fdtbus_get_data(), "/chosen"); + if (chosen_off < 0) + return; + + const uint64_t *map = fdt_getprop(fdtbus_get_data(), chosen_off, prop, &len); + if (map == NULL) + return; + + while (len >= 24) { + const paddr_t pa = be64toh(map[0]); + const vaddr_t va = be64toh(map[1]); + const size_t sz = be64toh(map[2]); +#if 0 + VPRINTF("%s: %s %#" PRIxPADDR "-%#" PRIxVADDR " (%#" PRIxVADDR + "-%#" PRIxVSIZE ")\n", __func__, prop, pa, pa + sz - 1, + va, va + sz - 1); +#endif + cpu_efirt_map_range(va, pa, sz, type); + map += 3; + len -= 24; + } +} +#endif void fdt_update_stdout_path(void *fdt, const char *boot_args) Index: src/sys/dev/fdt/fdt_boot.h diff -u src/sys/dev/fdt/fdt_boot.h:1.1 src/sys/dev/fdt/fdt_boot.h:1.2 --- src/sys/dev/fdt/fdt_boot.h:1.1 Sat Apr 22 09:53:45 2023 +++ src/sys/dev/fdt/fdt_boot.h Mon Jul 10 07:00:12 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_boot.h,v 1.1 2023/04/22 09:53:45 skrll Exp $ */ +/* $NetBSD: fdt_boot.h,v 1.2 2023/07/10 07:00:12 rin Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -32,6 +32,22 @@ #ifndef _DEV_FDT_FDT_BOOT_H_ #define _DEV_FDT_FDT_BOOT_H_ +#ifdef EFI_RUNTIME +#include <machine/efirt.h> + +void fdt_map_efi_runtime(const char *prop, enum cpu_efirt_mem_type type); +#endif + +void fdt_probe_initrd(void); +void fdt_setup_initrd(void); +void fdt_reserve_initrd(void); +void fdt_probe_rndseed(void); +void fdt_setup_rndseed(void); +void fdt_reserve_rndseed(void); +void fdt_probe_efirng(void); +void fdt_setup_efirng(void); +void fdt_reserve_efirng(void); + void fdt_update_stdout_path(void *, const char *); #endif /* _DEV_FDT_FDT_BOOT_H_ */ Added files: Index: src/sys/arch/arm/include/efirt.h diff -u /dev/null src/sys/arch/arm/include/efirt.h:1.1 --- /dev/null Mon Jul 10 07:00:12 2023 +++ src/sys/arch/arm/include/efirt.h Mon Jul 10 07:00:12 2023 @@ -0,0 +1,13 @@ +#ifndef _ARM_EFIRT_H_ +#define _ARM_EFIRT_H_ + + +enum cpu_efirt_mem_type { + ARM_EFIRT_MEM_CODE, + ARM_EFIRT_MEM_DATA, + ARM_EFIRT_MEM_MMIO, +}; + +void cpu_efirt_map_range(vaddr_t, paddr_t, size_t, enum cpu_efirt_mem_type); + +#endif Index: src/sys/arch/evbarm/include/efirt.h diff -u /dev/null src/sys/arch/evbarm/include/efirt.h:1.1 --- /dev/null Mon Jul 10 07:00:12 2023 +++ src/sys/arch/evbarm/include/efirt.h Mon Jul 10 07:00:12 2023 @@ -0,0 +1,3 @@ +/* $NetBSD: efirt.h,v 1.1 2023/07/10 07:00:12 rin Exp $ */ + +#include <arm/efirt.h>