Initial commit
This commit is contained in:
commit
5fa601852f
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!bible.c
|
||||||
|
!bible.h
|
||||||
|
!Makefile
|
||||||
|
!LICENSE
|
||||||
|
!README.md
|
|
@ -0,0 +1,19 @@
|
||||||
|
ifneq ($(KERNELRELEASE),)
|
||||||
|
obj-m := bible.o
|
||||||
|
|
||||||
|
else
|
||||||
|
KDIR ?= /lib/modules/`uname -r`/build
|
||||||
|
|
||||||
|
default:
|
||||||
|
$(MAKE) -C $(KDIR) M=$$PWD
|
||||||
|
|
||||||
|
clean:
|
||||||
|
find . \( -name '*.o' -or -name '*.ko' \) -delete
|
||||||
|
rm -f *.mod.c
|
||||||
|
rm -rf modules.order Module.symvers
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(MAKE) -C $(KDIR) M=$$PWD modules_install
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# bible
|
||||||
|
|
||||||
|
A Linux kernel module that adds The Holy Bible as a character device, /dev/bible.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
$ make
|
||||||
|
$ sudo make install
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
## Build dependencies
|
||||||
|
|
||||||
|
* Linux kernel headers
|
||||||
|
* make
|
||||||
|
* GCC
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/cdev.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
#include "bible.h"
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL"); //God's Parables and Liturgy
|
||||||
|
|
||||||
|
int init_module(void);
|
||||||
|
void cleanup_module(void);
|
||||||
|
static int device_open(struct inode *, struct file *);
|
||||||
|
static int device_release(struct inode *, struct file *);
|
||||||
|
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
|
||||||
|
static int on_dev_uevent(struct device*, struct kobj_uevent_env*);
|
||||||
|
|
||||||
|
#define DEVICE_NAME "bible"
|
||||||
|
|
||||||
|
static dev_t devt;
|
||||||
|
static struct class* device_class;
|
||||||
|
static struct device* device;
|
||||||
|
static struct cdev character_device;
|
||||||
|
|
||||||
|
static struct file_operations fops = {
|
||||||
|
.read = device_read,
|
||||||
|
.open = device_open,
|
||||||
|
.release = device_release
|
||||||
|
};
|
||||||
|
|
||||||
|
int init_module(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if((result = alloc_chrdev_region(&devt, 0, 1, DEVICE_NAME)) < 0)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Couldn't alloc chrdev region: %d\n", result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((device_class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Couldn't create device class\n");
|
||||||
|
|
||||||
|
unregister_chrdev_region(devt, 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_class->dev_uevent = on_dev_uevent;
|
||||||
|
|
||||||
|
if((device = device_create(device_class, NULL, devt, NULL, DEVICE_NAME)) == NULL)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Couldn't create device\n");
|
||||||
|
|
||||||
|
class_destroy(device_class);
|
||||||
|
unregister_chrdev_region(devt, 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdev_init(&character_device, &fops);
|
||||||
|
|
||||||
|
if((result = cdev_add(&character_device, devt, 1)) < 0)
|
||||||
|
{
|
||||||
|
printk(KERN_ALERT "Couldn't add character device\n");
|
||||||
|
|
||||||
|
device_destroy(device_class, devt);
|
||||||
|
class_destroy(device_class);
|
||||||
|
unregister_chrdev_region(devt, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_module(void)
|
||||||
|
{
|
||||||
|
device_destroy(device_class, devt);
|
||||||
|
class_destroy(device_class);
|
||||||
|
unregister_chrdev_region(devt, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
|
{
|
||||||
|
add_uevent_var(env, "DEVMODE=%#o", 0444);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int device_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
try_module_get(THIS_MODULE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int device_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
module_put(THIS_MODULE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if(*offset + length > bible_txt_len)
|
||||||
|
{
|
||||||
|
length = bible_txt_len - *offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < length; i++)
|
||||||
|
{
|
||||||
|
put_user(*(bible_txt + *offset + i), buffer + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset += length;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
Loading…
Reference in New Issue