Hi. This is my first post to FreeBSD-Hackers. It's probably the wrong place at the wrong time and totaly inappropriate in general, so start flaming right now. Anyway, I've writting a small patch to enable the thermal noise random number generator found in the i82802 (i82810). It breaks the /dev/random semantics slightly as the bitpool never run out of fresh bits. Hopefully somebody finds it usefull :-). I do. BTW, the patch is against the REL-3.3 kernel and x86-only. /Bjorn
diff -Nru sys.orig/i386/conf/files.i386 sys/i386/conf/files.i386 --- sys.orig/i386/conf/files.i386 Mon Sep 6 00:35:34 1999 +++ sys/i386/conf/files.i386 Fri Jan 7 00:21:44 2000 @@ -79,6 +79,7 @@ i386/i386/globals.s standard i386/i386/i386-gdbstub.c optional ddb i386/i386/i686_mem.c standard +i386/i386/i82802_rng.c standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet i386/i386/initcpu.c standard diff -Nru sys.orig/i386/i386/i82802_rng.c sys/i386/i386/i82802_rng.c --- sys.orig/i386/i386/i82802_rng.c Thu Jan 1 00:00:00 1970 +++ sys/i386/i386/i82802_rng.c Fri Jan 7 09:38:43 2000 @@ -0,0 +1,68 @@ +/* $Id$ + * + * Copyright (c) 2000 Bjorn Ahlqvist. + * All rights reserved. + * + * v1.0 - Initial version. + * + * TODO: We should make sure we're really receiving something + * that look random. The specification suggests FIPS 140-1. + * + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +#include <machine/clock.h> +#include <machine/random.h> + +#define I82802_RNG_NAME "i82802 thermal noise random number generator" + +#define I82802_HW_RNG_ENABLE 1 /* hw_status */ +#define I82802_HW_RNG_PRESENT 0x40 /* hw_status */ +#define I82802_RNG_DATA_PRESENT 1 /* rng_status */ +#define I82802_RNG_BASE 0xffbc0000 /* absolute address */ +#define I82802_RNG_DELAY 5 /* about 4.5 ms */ + +struct i82802_rng { + u_char fill[0x015f]; + u_char hw_status; + u_char rng_status; + u_char rng_data; +}; + + +static struct i82802_rng *rngp; +int rng_present; + +u_char rng_read(void) +{ + while(!(rngp->rng_status&I82802_RNG_DATA_PRESENT)) { /* wait.. */ + if(!curproc) DELAY(I82802_RNG_DELAY); /* ..for data */ + else tsleep(&rng_read,PRIBIO,"rngrd",1); + } + + return(rngp->rng_data); /* got some */ +} + +static void rng_probe(void *dummy) +{ + rngp=pmap_mapdev(I82802_RNG_BASE,sizeof(*rngp)); /* wire mem */ + + rng_present=rngp->hw_status&I82802_HW_RNG_PRESENT; /* present? */ + if(!rng_present) return; /* no return */ + rngp->hw_status|=I82802_HW_RNG_ENABLE; /* yes enable */ + + printf(I82802_RNG_NAME" at 0x%08x enabled.\n",I82802_RNG_BASE); +} + +SYSINIT(rng,SI_SUB_DRIVERS,SI_ORDER_ANY,rng_probe,NULL) + diff -Nru sys.orig/i386/include/random.h sys/i386/include/random.h --- sys.orig/i386/include/random.h Sun Aug 29 16:06:47 1999 +++ sys/i386/include/random.h Fri Jan 7 02:34:17 2000 @@ -66,8 +66,13 @@ int sc_intr; }; +/* Exported variables */ + +extern int rng_present; + /* Exported functions */ +u_char rng_read(void); void rand_initialize(void); void add_keyboard_randomness(u_char scancode); inthand2_t add_interrupt_randomness; diff -Nru sys.orig/i386/isa/random_machdep.c sys/i386/isa/random_machdep.c --- sys.orig/i386/isa/random_machdep.c Sun Aug 29 16:07:31 1999 +++ sys/i386/isa/random_machdep.c Fri Jan 7 09:36:37 2000 @@ -325,6 +325,13 @@ u_int read_random(void *buf, u_int nbytes) { + int i; + + if (rng_present) { /* Hardware RNG */ + for(i=0;i<nbytes;i++) *((u_char *)buf)++=rng_read(); + return nbytes; + } + if ((nbytes * 8) > random_state.entropy_count) nbytes = random_state.entropy_count / 8;