New Generic HW RNG
Subsystems (5)
cover New Generic HW RNG
This patch series replaces the old non-generic Hardware Random Number Generator support by a fully generic RNG API.
This makes it possible to register additional RNGs from modules. With this patch series applied, Laptops with a bcm43xx chip (PowerBook) have a HW RNG available now.
Additionally two new RNG drivers are added for the "ixp4xx" and "omap" devices. (Written by Deepak Saxena). This patch series includes the old patches by Deepak Saxena.
The x86-rng driver is the old RNG driver ported to the new API (and cleaned up a bit).
Please apply to -mm for testing.
PATCH 1/6 New Generic HW RNG
Remove the old H/W RNG support.
drivers/char/Kconfig +0 -15
@@ -670,21 +670,6 @@ If you're not sure, say N. -config HW_RANDOM - tristate "Intel/AMD/VIA HW Random Number Generator support" - depends on (X86 || IA64) && PCI - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on Intel i8xx-based motherboards, - AMD 76x-based motherboards, and Via Nehemiah CPUs. - - Provides a character driver, used to read() entropy data. - - To compile this driver as a module, choose M here: the - module will be called hw_random. - - If unsure, say N. - config NVRAM tristate "/dev/nvram support" depends on ATARI || X86 || ARM || GENERIC_NVRAM
drivers/char/Makefile +0 -1
@@ -75,7 +75,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o -obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_PPDEV) += ppdev.o
drivers/char/hw_random.c deleted +0 -698
698 lines not on this page · raw message
--
PATCH 2/6 New Generic HW RNG
In reply to Michael BueschAdd a new generic H/W RNG core.
drivers/char/Kconfig +2 -0
@@ -670,6 +670,8 @@ If you're not sure, say N. +source "drivers/char/hw_random/Kconfig" + config NVRAM tristate "/dev/nvram support" depends on ATARI || X86 || ARM || GENERIC_NVRAM
drivers/char/Makefile +1 -0
@@ -75,6 +75,7 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o +obj-$(CONFIG_HW_RANDOM) += hw_random/ obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_PPDEV) += ppdev.o
drivers/char/hw_random/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +# +# Hardware Random Number Generator (RNG) configuration +# + +config HW_RANDOM + bool "Hardware Random Number Generator Core support" + default y + ---help--- + Hardware Random Number Generator Core infrastructure. + + If unsure, say Y.
drivers/char/hw_random/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +# +# Makefile for HW Random Number Generator (RNG) device drivers. +# + +obj-$(CONFIG_HW_RANDOM) += core.o
drivers/char/hw_random/core.c new file +324 -0
324 lines not on this page · raw message
--
Quoted 3 lines · On Sun, 07 May 2006 13:35:15 +0200 Michael Buesch wrote:
Add a new generic H/W RNG core.
Signed-off-by Michael Buesch <[email protected]>
[skip]
Quoted 71 lines
Index:
hwrng/drivers/char/hw_random/core.c
===================================================================drivers/char/hw_random/core.c new file +66
-0@@ -0,0 +1,324 @@ +/* +Added support for the AMD Geode LX RNG +(c) Copyright 2004-2005 Advanced Micro Devices, Inc. + +derived from + +Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) +(c) Copyright 2003 Red Hat Inc <[email protected]> + +derived from + +Hardware driver for the AMD 768 Random Number Generator (RNG) +(c) Copyright 2001 Red Hat Inc <[email protected]> + +derived from + +Hardware driver for Intel i810 Random Number Generator (RNG) +Copyright 2000,2001 Jeff Garzik <[email protected]> +Copyright 2000,2001 Philipp Rumpf <[email protected]> + +Added generic RNG API +Copyright 2006 Michael Buesch <[email protected]> +Copyright 2005 (c) MontaVista Software, Inc. + +Please read Documentation/hw_random.txt for details on use. + +---------------------------------------------------------- +This software may be used and distributed according to the terms +of the GNU General Public License, incorporated herein by reference. + +*/ + + +#include <linux/device.h> +#include <linux/hw_random.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/delay.h> +#include <asm/uaccess.h> + + +#define RNG_MODULE_NAME "hw_random" +#define PFX RNG_MODULE_NAME ": " +#define RNG_MISCDEV_MINOR 183/* official */ + + +static struct hwrng *current_rng; +static LIST_HEAD (rng_list); +static DEFINE_MUTEX (rng_mutex); + + +static int rng_dev_open (struct inode *inode,struct file *filp) +{ +/* enforce read-only access to this chrdev */ +if ((filp->f_mode &FMODE_READ ) ==0 ) +return -EINVAL ; +if (filp->f_mode &FMODE_WRITE ) +return -EINVAL ; +return 0 ; +} + +static ssize_t rng_dev_read (struct file *filp,char __user *buf, +size_t size,loff_t *offp)
drivers/char/hw_random/core.c line 76
Quoted 10 lines
drivers/char/hw_random/core.c new file +10
-0+{ +unsigned int have_data; +u32 data =0 ; +ssize_t ret =0 ; +int i, err; + +while (size) { + err =mutex_lock_interruptible (&rng_mutex); +if (err) +return err;
This does not handle the case of partial read correctly - the code should be
return ret ? : -ERESTARTSYS;
drivers/char/hw_random/core.c line 79
Quoted 3 lines
drivers/char/hw_random/core.c new file +3
-0+if (!current_rng) { +mutex_unlock (&rng_mutex); +return -ENODEV ;
The same problem here (although finding the RNG suddenly missing after we heve just read something from it is pretty unlikely).
Quoted 17 lines
drivers/char/hw_random/core.c new file +17
-0+ } + have_data =0 ; +if (current_rng->data_present ==NULL || + current_rng->data_present (current_rng)) + have_data = current_rng->data_read (current_rng, &data); +mutex_unlock (&rng_mutex); + +while (have_data && size) { +if (put_user ((u8 )data, buf++)) { + ret = ret ? : -EFAULT ; +break ; + } + size--; + ret++; + have_data--; + data>>=8 ; + }
drivers/char/hw_random/core.c line 106
Quoted 10 lines
drivers/char/hw_random/core.c new file +10
-0+ +if (filp->f_flags &O_NONBLOCK ) +return ret ? : -EAGAIN ; + +if (need_resched ()) { +schedule_timeout_interruptible (1 ); + }else { + err =mutex_lock_interruptible (&rng_mutex); +if (err) +return err;
And here...
drivers/char/hw_random/core.c line 79
Quoted 3 lines
drivers/char/hw_random/core.c new file +3
-0+if (!current_rng) { +mutex_unlock (&rng_mutex); +return -ENODEV ;
And here too.
Quoted 35 lines
drivers/char/hw_random/core.c new file +35
-0+ } +for (i =0 ; i <20 ; i++) { +if (current_rng->data_present ==NULL || + current_rng->data_present (current_rng)) +break ; +udelay (10 ); + } +mutex_unlock (&rng_mutex); + } + +if (signal_pending (current)) +return ret ? : -ERESTARTSYS ; + } +return ret; +} + + +static struct file_operations rng_chrdev_ops = { + .owner =THIS_MODULE , + .open = rng_dev_open, + .read = rng_dev_read, +}; + +static struct miscdevice rng_miscdev = { + .minor =RNG_MISCDEV_MINOR , + .name =RNG_MODULE_NAME , + .fops = &rng_chrdev_ops, +}; + + +static ssize_t hwrng_attr_current_store (struct class_device *class, +const char *buf,size_t len) +{ +int err; +struct hwrng *rng;
drivers/char/hw_random/core.c line 154
Quoted 10 lines
drivers/char/hw_random/core.c new file +10
-0+ +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ; + + err =mutex_lock_interruptible (&rng_mutex); +if (err) +return err; + err = -ENODEV ; +list_for_each_entry (rng, &rng_list, list) { +if (strncmp (rng->name, buf, len) ==0 ) {
This will match if the passed string is just a prefix of rng->name. Apparently sysfs guarantees that the buffer passed to ->store will be NUL-terminated, so this should be just a strcmp().
drivers/char/hw_random/core.c line 161
Quoted 7 lines
drivers/char/hw_random/core.c new file +7
-0+if (rng->init) { + err = rng->init (rng); +if (err) +break ; + } +if (current_rng && current_rng->cleanup) + current_rng->cleanup (current_rng);
What if rng == current_rng here (someone has written the same RNG name to the "store" attribute)? The lowlevel RNG driver should not have to handle nested init/cleanup calls.
[skip]
Quoted 42 lines · you
This does not handle the case of partial read correctly - the code should be
return ret ? : -ERESTARTSYS;drivers/char/hw_random/core.c line 79
Quoted 3 lines
drivers/char/hw_random/core.c new file +3
-0+if (!current_rng) { +mutex_unlock (&rng_mutex); +return -ENODEV ;The same problem here (although finding the RNG suddenly missing after we heve just read something from it is pretty unlikely).
Quoted 17 lines
drivers/char/hw_random/core.c new file +17
-0+ } + have_data =0 ; +if (current_rng->data_present ==NULL || + current_rng->data_present (current_rng)) + have_data = current_rng->data_read (current_rng, &data); +mutex_unlock (&rng_mutex); + +while (have_data && size) { +if (put_user ((u8 )data, buf++)) { + ret = ret ? : -EFAULT ; +break ; + } + size--; + ret++; + have_data--; + data>>=8 ; + }drivers/char/hw_random/core.c line 106
Quoted 10 lines
drivers/char/hw_random/core.c new file +10
-0+ +if (filp->f_flags &O_NONBLOCK ) +return ret ? : -EAGAIN ; + +if (need_resched ()) { +schedule_timeout_interruptible (1 ); + }else { + err =mutex_lock_interruptible (&rng_mutex); +if (err) +return err;And here...
Quoted 5 lines
drivers/char/hw_random/core.c line 79
Quoted 3 lines
drivers/char/hw_random/core.c new file +3
-0+if (!current_rng) { +mutex_unlock (&rng_mutex); +return -ENODEV ;And here too.
Whoops, will fix these.
Quoted 6 lines
drivers/char/hw_random/core.c line 154
Quoted 2 lines
drivers/char/hw_random/core.c new file +2
-0+list_for_each_entry (rng, &rng_list, list) { +if (strncmp (rng->name, buf, len) ==0 ) {This will match if the passed string is just a prefix of
rng->name. Apparently sysfs guarantees that the buffer passed to ->store will be NUL-terminated, so this should be just astrcmp().
I am not sure if it is guaranteed NUL terminated. Greg? But I will look into this.
Quoted 11 lines
drivers/char/hw_random/core.c line 161
Quoted 7 lines
drivers/char/hw_random/core.c new file +7
-0+if (rng->init) { + err = rng->init (rng); +if (err) +break ; + } +if (current_rng && current_rng->cleanup) + current_rng->cleanup (current_rng);What if rng ==
current_rnghere (someone has written the same RNG name to the "store" attribute)? The lowlevel RNG driver should not have to handle nested init/cleanup calls.
I see. Will fix this.
I will also fix the bcm43xx patch. It registers always with the same "name". That will blow up, if there is more than one bcm43xx device in the system.
Signature · 1 line
Greetings Michael.
Quoted 5 lines · you
Quoted 4 lines · you
This does not handle the case of partial read correctly - the code should be
return ret ? : -ERESTARTSYS;
Or, hm. Shouldn't we
return ret ? : err;
err is -EINTR
Signature · 1 line
Greetings Michael.
Quoted 11 lines · Michael Buesch
Quoted 5 lines · you
Quoted 4 lines · you
This does not handle the case of partial read correctly - the code should be
return ret ? : -ERESTARTSYS;Or, hm. Shouldn't we
return ret ? : err;err is
-EINTR
-ERESTARTSYS is the proper return code for this case - the signal handling code will either convert it to EINTR for userspace, or restart the system call after handling the signal, depending on the state of the SA_RESTART flag set by sigaction().
Quoted 11 lines · you
Quoted 10 lines · Michael Buesch
Quoted 5 lines · you
Quoted 4 lines · you
This does not handle the case of partial read correctly - the code should be
return ret ? : -ERESTARTSYS;Or, hm. Shouldn't we
return ret ? : err;
Quoted 6 lines
Quoted 1 line
err is
-EINTR
-ERESTARTSYSis the proper return code for this case - the signal handling code will either convert it to EINTR for userspace, or restart the system call after handling the signal, depending on the state of theSA_RESTARTflag set bysigaction().
Ok, I fixed all your stuff. Thanks.
I will run some more tests now and re-submit, if noone else finds a bug. ;)
Signature · 1 line
Greetings Michael.
Quoted 10 lines · Michael Buesch
Quoted 6 lines · you
drivers/char/hw_random/core.c line 154
Quoted 2 lines
drivers/char/hw_random/core.c new file +2
-0+list_for_each_entry (rng, &rng_list, list) { +if (strncmp (rng->name, buf, len) ==0 ) {This will match if the passed string is just a prefix of
rng->name. Apparently sysfs guarantees that the buffer passed to ->store will be NUL-terminated, so this should be just astrcmp().I am not sure if it is guaranteed NUL terminated. Greg? But I will look into this.
Yes it will be.
thanks,
greg k-h
Quoted 9 lines · you
Quoted 8 lines · Michael Buesch
Quoted 6 lines · you
drivers/char/hw_random/core.c line 154
Quoted 2 lines
drivers/char/hw_random/core.c new file +2
-0+list_for_each_entry (rng, &rng_list, list) { +if (strncmp (rng->name, buf, len) ==0 ) {This will match if the passed string is just a prefix of
rng->name. Apparently sysfs guarantees that the buffer passed to ->store will be NUL-terminated, so this should be just astrcmp().
Quoted 4 lines
Quoted 2 lines
I am not sure if it is guaranteed NUL terminated. Greg? But I will look into this.
Yes it will be.
Ok, very nice.
I will resend the patches as soon as I have some time.
I also splitted up the x86 drivers. Looks very good and clean now. ;)
Signature · 1 line
Greetings Michael.
PATCH 3/6 New Generic HW RNG
In reply to Michael BueschAdd a driver for the x86 RNG.
This driver is ported from the old hw_random.c
drivers/char/hw_random/Kconfig +13 -0
@@ -9,3 +9,16 @@ Hardware Random Number Generator Core infrastructure. If unsure, say Y. + +config X86_RNG + tristate "Intel/AMD/VIA HW Random Number Generator support" + depends on HW_RANDOM && (X86 || IA64) && PCI + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Intel i8xx-based motherboards, + AMD 76x-based motherboards, and Via Nehemiah CPUs. + + To compile this driver as a module, choose M here: the + module will be called x86-rng. + + If unsure, say Y.
drivers/char/hw_random/Makefile +1 -0
@@ -3,3 +3,4 @@ # obj-$(CONFIG_HW_RANDOM) += core.o +obj-$(CONFIG_X86_RNG) += x86-rng.o
drivers/char/hw_random/x86-rng.c new file +586 -0
586 lines not on this page · raw message
--
Quoted 2 lines · On Sun, 07 May 2006 13:35:16 +0200 Michael Buesch wrote:
Add a driver for the x86 RNG.
This driver is ported from the oldhw_random.c
In fact, this is 4 completely different drivers - probably they should be split now?
Quoted 7 lines · you
Quoted 2 lines · On Sun, 07 May 2006 13:35:16 +0200 Michael Buesch wrote:
Add a driver for the x86 RNG.
This driver is ported from the oldhw_random.cIn fact, this is 4 completely different drivers - probably they should be split now?
I can split them, it it is really desired to do this in this patch series. It can also be done later.
What should I do?
Signature · 1 line
Greetings Michael.
PATCH 4/6 New Generic HW RNG
In reply to Michael BueschAdd ixp4xx H/W RNG driver.
Driver written by Deepak Saxena.
drivers/char/hw_random/Kconfig +12 -0
@@ -22,3 +22,15 @@ module will be called x86-rng. If unsure, say Y. + +config IXP4XX_RNG + tristate "Intel IXP4xx NPU HW Random Number Generator support" + depends on HW_RANDOM && ARCH_IXP4XX + ---help--- + This driver provides kernel-side support for the Random + Number Generator hardware found on the Intel IXP4xx NPU. + + To compile this driver as a module, choose M here: the + module will be called ixp4xx-rng. + + If unsure, say Y.
drivers/char/hw_random/Makefile +1 -0
@@ -4,3 +4,4 @@ obj-$(CONFIG_HW_RANDOM) += core.o obj-$(CONFIG_X86_RNG) += x86-rng.o +obj-$(CONFIG_IXP4XX_RNG) += ixp4xx-rng.o
drivers/char/hw_random/ixp4xx-rng.c new file +73 -0
73 lines not on this page · raw message
--
PATCH 5/6 New Generic HW RNG
In reply to Michael BueschAdd H/W RNG driver for TI OMAP CPU family.
Driver written by Deepak Saxena.
drivers/char/hw_random/Kconfig +13 -0
@@ -34,3 +34,16 @@ module will be called ixp4xx-rng. If unsure, say Y. + +config OMAP_RNG + tristate "OMAP Random Number Generator support" + depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on OMAP16xx and OMAP24xx multimedia + processors. + + To compile this driver as a module, choose M here: the + module will be called omap-rng. + + If unsure, say Y.
drivers/char/hw_random/Makefile +1 -0
@@ -5,3 +5,4 @@ obj-$(CONFIG_HW_RANDOM) += core.o obj-$(CONFIG_X86_RNG) += x86-rng.o obj-$(CONFIG_IXP4XX_RNG) += ixp4xx-rng.o +obj-$(CONFIG_OMAP_RNG) += omap-rng.o
drivers/char/hw_random/omap-rng.c new file +208 -0
208 lines not on this page · raw message
--
PATCH 6/6 New Generic HW RNG
In reply to Michael BueschAdd bcm43xx H/W RNG support.
drivers/net/wireless/bcm43xx/Kconfig +1 -0
@@ -2,6 +2,7 @@ tristate "Broadcom BCM43xx wireless support" depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL select FW_LOADER + select HW_RANDOM ---help--- This is an experimental driver for the Broadcom 43xx wireless chip, found in the Apple Airport Extreme and various other devices.
drivers/net/wireless/bcm43xx/bcm43xx.h +5 -0
@@ -1,6 +1,7 @@#ifndef BCM43xx_H_#define BCM43xx_H_ +#include <linux/hw_random.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/spinlock.h>
@@ -82,6 +83,7 @@#define BCM43xx_MMIO_TSF_1 0x634/* core rev < 3 only */ #define BCM43xx_MMIO_TSF_2 0x636/* core rev < 3 only */ #define BCM43xx_MMIO_TSF_3 0x638/* core rev < 3 only */ +#define BCM43xx_MMIO_RNG 0x65A#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8/* SPROM offsets. */
@@ -741,6 +743,9 @@const struct firmware *initvals0;const struct firmware *initvals1; +/* Random Number Generator. */ +struct hwrng rng; +/* Debugging stuff follows. */ #ifdef CONFIG_BCM43XX_DEBUG struct bcm43xx_dfsentry *dfsentry;
drivers/net/wireless/bcm43xx/bcm43xx_main.c +35 -0
@@ -3144,6 +3144,37 @@bcm43xx_clear_keys (bcm); } +static int bcm43xx_rng_read (struct hwrng *rng,u32 *data) +{ +struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; +unsigned long flags; + +bcm43xx_lock (bcm, flags); + *data =bcm43xx_read16 (bcm, BCM43xx_MMIO_RNG); +bcm43xx_unlock (bcm, flags); + +return (sizeof (u16)); +} + +static void bcm43xx_rng_exit (struct bcm43xx_private *bcm) +{ +hwrng_unregister (&bcm->rng); +} + +static int bcm43xx_rng_init (struct bcm43xx_private *bcm) +{ +int err; + + bcm->rng.name =KBUILD_MODNAME ; + bcm->rng.data_read = bcm43xx_rng_read; + bcm->rng.priv = (unsigned long )bcm; + err =hwrng_register (&bcm->rng); +if (err) + printk(KERN_ERR PFX "RNG init failed\n"); + +return err; +} +/* This is the opposite of bcm43xx_init_board() */ static void bcm43xx_free_board (struct bcm43xx_private *bcm) {
@@ -3159,6 +3190,7 @@ bcm->shutting_down =1 ;bcm43xx_unlock (bcm, flags); +bcm43xx_rng_exit (bcm);for (i =0 ; i < BCM43xx_MAX_80211_CORES; i++) {if (!bcm->core_80211[i].available)continue ;
@@ -3240,6 +3272,9 @@bcm43xx_switch_core (bcm, &bcm->core_80211[0 ]);bcm43xx_mac_enable (bcm); } + err =bcm43xx_rng_init (bcm); +if (err) + goto err_80211_unwind;bcm43xx_macfilter_clear (bcm, BCM43xx_MACFILTER_ASSOC);bcm43xx_macfilter_set (bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); dprintk(KERN_INFO PFX "80211 cores initialized\n");
--