121 lines · 2.5 KB · C
RawDownload
/* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,addtoit}.com> */ /* Much of this ripped from drivers/char/hw_random.c, see there for other * copyright. * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. */#include <linux/sched/signal.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/interrupt.h>#include <linux/miscdevice.h>#include <linux/hw_random.h>#include <linux/delay.h>#include <linux/uaccess.h>#include <init.h>#include <irq_kern.h>#include <os.h> /* * core module information */#define RNG_MODULE_NAME "hw_random" /* Changed at init time, in the non-modular case, and at module load * time, in the module case.  Presumably, the module subsystem * protects against a module being loaded twice at the same time. */static int random_fd = -1;static struct hwrng hwrng;static DECLARE_COMPLETION(have_data); static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block){	int ret; 	for (;;) {		ret = os_read_file(random_fd, buf, max);		if (block && ret == -EAGAIN) {			add_sigio_fd(random_fd); 			ret = wait_for_completion_killable(&have_data); 			ignore_sigio_fd(random_fd);			deactivate_fd(random_fd, RANDOM_IRQ); 			if (ret < 0)				break;		} else {			break;		}	} 	return ret != -EAGAIN ? ret : 0;} static irqreturn_t random_interrupt(int irq, void *data){	complete(&have_data); 	return IRQ_HANDLED;} /* * rng_init - initialize RNG module */static int __init rng_init (void){	int err; 	err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);	if (err < 0)		goto out; 	random_fd = err;	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,			     0, "random", NULL);	if (err < 0)		goto err_out_cleanup_hw; 	sigio_broken();	hwrng.name = RNG_MODULE_NAME;	hwrng.read = rng_dev_read; 	err = hwrng_register(&hwrng);	if (err) {		pr_err(RNG_MODULE_NAME " registering failed (%d)\n", err);		goto err_out_cleanup_hw;	}out:	return err; err_out_cleanup_hw:	os_close_file(random_fd);	random_fd = -1;	goto out;} /* * rng_cleanup - shutdown RNG module */ static void cleanup(void){	free_irq_by_fd(random_fd);	os_close_file(random_fd);} static void __exit rng_cleanup(void){	hwrng_unregister(&hwrng);	os_close_file(random_fd);} module_init (rng_init);module_exit (rng_cleanup);__uml_exitcall(cleanup); MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");MODULE_LICENSE("GPL");