Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src-draft/trunk]: src/sys/stand/efiboot Pass EFI RNG output via /chosen/netb...



details:   https://anonhg.NetBSD.org/src-all/rev/996ce8f9ccff
branches:  trunk
changeset: 932723:996ce8f9ccff
user:      Taylor R Campbell <riastradh%NetBSD.org@localhost>
date:      Mon May 11 02:11:09 2020 +0000

description:
Pass EFI RNG output via /chosen/netbsd,efirng-{start,end}.

This is separate from /chosen/netbsd,rndseed-{start,end}, which
specifies NetBSD's persistent on-disk seed; efirng is the firmware's
RNG device.

diffstat:

 sys/stand/efiboot/efiboot.c |   2 +
 sys/stand/efiboot/efifdt.c  |  24 ++++++++++++++++++++++
 sys/stand/efiboot/efifdt.h  |   1 +
 sys/stand/efiboot/exec.c    |  48 +++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 73 insertions(+), 2 deletions(-)

diffs (153 lines):

diff -r e6085e29ece7 -r 996ce8f9ccff sys/stand/efiboot/efiboot.c
--- a/sys/stand/efiboot/efiboot.c       Mon May 11 02:10:19 2020 +0000
+++ b/sys/stand/efiboot/efiboot.c       Mon May 11 02:11:09 2020 +0000
@@ -31,6 +31,7 @@
 #include "efiblock.h"
 #include "efifdt.h"
 #include "efiacpi.h"
+#include "efirng.h"
 
 #include <sys/reboot.h>
 
@@ -99,6 +100,7 @@
        efi_net_probe();
        efi_file_system_probe();
        efi_block_probe();
+       efi_rng_probe();
 
        boot();
 
diff -r e6085e29ece7 -r 996ce8f9ccff sys/stand/efiboot/efifdt.c
--- a/sys/stand/efiboot/efifdt.c        Mon May 11 02:10:19 2020 +0000
+++ b/sys/stand/efiboot/efifdt.c        Mon May 11 02:11:09 2020 +0000
@@ -391,6 +391,7 @@
        fdt_setprop_u64(fdt_data, chosen, "linux,initrd-end", initrd_addr + initrd_size);
 }
 
+/* pass in the NetBSD on-disk random seed */
 void
 efi_fdt_rndseed(u_long rndseed_addr, u_long rndseed_size)
 {
@@ -412,3 +413,26 @@
        fdt_setprop_u64(fdt_data, chosen, "netbsd,rndseed-end",
            rndseed_addr + rndseed_size);
 }
+
+/* pass in output from the EFI firmware's RNG from some unknown source */
+void
+efi_fdt_efirng(u_long efirng_addr, u_long efirng_size)
+{
+       int chosen;
+
+       if (efirng_size == 0)
+               return;
+
+       chosen = fdt_path_offset(fdt_data, FDT_CHOSEN_NODE_PATH);
+       if (chosen < 0)
+               chosen = fdt_add_subnode(fdt_data,
+                   fdt_path_offset(fdt_data, "/"),
+                   FDT_CHOSEN_NODE_NAME);
+       if (chosen < 0)
+               panic("FDT: Failed to create " FDT_CHOSEN_NODE_PATH " node");
+
+       fdt_setprop_u64(fdt_data, chosen, "netbsd,efirng-start",
+           efirng_addr);
+       fdt_setprop_u64(fdt_data, chosen, "netbsd,efirng-end",
+           efirng_addr + efirng_size);
+}
diff -r e6085e29ece7 -r 996ce8f9ccff sys/stand/efiboot/efifdt.h
--- a/sys/stand/efiboot/efifdt.h        Mon May 11 02:10:19 2020 +0000
+++ b/sys/stand/efiboot/efifdt.h        Mon May 11 02:11:09 2020 +0000
@@ -38,5 +38,6 @@
 void efi_fdt_bootargs(const char *);
 void efi_fdt_initrd(u_long, u_long);
 void efi_fdt_rndseed(u_long, u_long);
+void efi_fdt_efirng(u_long, u_long);
 void efi_fdt_init(u_long, u_long);
 void efi_fdt_fini(void);
diff -r e6085e29ece7 -r 996ce8f9ccff sys/stand/efiboot/exec.c
--- a/sys/stand/efiboot/exec.c  Mon May 11 02:10:19 2020 +0000
+++ b/sys/stand/efiboot/exec.c  Mon May 11 02:11:09 2020 +0000
@@ -31,6 +31,7 @@
 #include "efienv.h"
 #include "efifdt.h"
 #include "efiacpi.h"
+#include "efirng.h"
 
 #include <sys/reboot.h>
 
@@ -41,8 +42,8 @@
 #define        FDT_SPACE       (4 * 1024 * 1024)
 #define        FDT_ALIGN       ((2 * 1024 * 1024) - 1)
 
-static EFI_PHYSICAL_ADDRESS initrd_addr, dtb_addr, rndseed_addr;
-static u_long initrd_size = 0, dtb_size = 0, rndseed_size = 0;
+static EFI_PHYSICAL_ADDRESS initrd_addr, dtb_addr, rndseed_addr, efirng_addr;
+static u_long initrd_size = 0, dtb_size = 0, rndseed_size = 0, efirng_size = 0;
 
 static int
 load_file(const char *path, u_long extra, bool quiet_errors,
@@ -273,6 +274,47 @@
        prop_object_iterator_release(iter);
 }
 
+static void
+generate_efirng(void)
+{
+       EFI_PHYSICAL_ADDRESS addr;
+       u_long size = EFI_PAGE_SIZE;
+       EFI_STATUS status;
+
+       /* Check whether the RNG is available before bothering.  */
+       if (!efi_rng_available())
+               return;
+
+       /*
+        * Allocate a page.  This is the smallest unit we can pass into
+        * the kernel conveniently.
+        */
+#ifdef EFIBOOT_ALLOCATE_MAX_ADDRESS
+       addr = EFIBOOT_ALLOCATE_MAX_ADDRESS;
+       status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+           EfiLoaderData, EFI_SIZE_TO_PAGES(size), &addr);
+#else
+       addr = 0;
+       status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages,
+           EfiLoaderData, EFI_SIZE_TO_PAGES(size), &addr);
+#endif
+       if (EFI_ERROR(status)) {
+               Print(L"Failed to allocate page for EFI RNG output: %r\n",
+                   status);
+               return;
+       }
+
+       /* Fill the page with whatever the EFI RNG will do.  */
+       if (efi_rng((void *)(uintptr_t)addr, size)) {
+               uefi_call_wrapper(BS->FreePages, 2, addr, size);
+               return;
+       }
+
+       /* Success!  */
+       efirng_addr = addr;
+       efirng_size = size;
+}
+
 int
 exec_netbsd(const char *fname, const char *args)
 {
@@ -283,6 +325,7 @@
 
        load_file(get_initrd_path(), 0, false, &initrd_addr, &initrd_size);
        load_file(get_dtb_path(), 0, false, &dtb_addr, &dtb_size);
+       generate_efirng();
 
        memset(marks, 0, sizeof(marks));
        ohowto = howto;
@@ -346,6 +389,7 @@
                load_fdt_overlays();
                efi_fdt_initrd(initrd_addr, initrd_size);
                efi_fdt_rndseed(rndseed_addr, rndseed_size);
+               efi_fdt_efirng(efirng_addr, efirng_size);
                efi_fdt_bootargs(args);
 #ifdef EFIBOOT_ACPI
                if (efi_acpi_available())



Home | Main Index | Thread Index | Old Index