diff options
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | debug.c | 100 | ||||
-rw-r--r-- | debug.h | 10 | ||||
-rw-r--r-- | main.c | 46 | ||||
-rw-r--r-- | main.h | 7 |
5 files changed, 186 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4104b64 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +#ccflags-y += -g + +# Makfile assignments: +# := value at right is expanded and assigned at declaration time +# = value at right is expanded only when it is used, hence it is a reference +# ?= value at right is assigned only if the variable doesn't have a value +# +# + +# objects that are part of hello module (hello.o) +hello-y += main.o debug.o + +# .ko module to be created +obj-m := hello.o + +# '-C' changes the dir +# '-M' causes the the kernel's toplevel Makefile to move back into this dir +# before trying to build 'modules' target +all: + make -C /lib/modules/$(shell uname -r)/build KCPPFLAGS="-I$(CURDIR)" M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean @@ -0,0 +1,100 @@ +/* + * debug.c + * + * utilize debufs + * FIXME: R/W from /sys/kernel/debug/hello/magic doesn't work + * + */ + +#include <linux/debugfs.h> +#include <linux/types.h> +#include <linux/errno.h> + +#include <debug.h> +#include <main.h> + +#define BUFF_LEN 256 +char kernel_buff[BUFF_LEN] = {'f','o','o','b','a','r','\0'}; + +/* debugfs_create_file's 4th param + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + */ +int fileprv = 1; /* hmm */ + +/* struct file, an abstract open file, not on disk, which would be a an inode */ +static ssize_t debugfs_read(struct file *fp, char __user /* userspace */ *ubuff, size_t c, loff_t *pos) +{ + /** + * simple_read_from_buffer - copy data from the buffer to user space + * @to: the user space buffer to read to + * @count: the maximum number of bytes to read + * @ppos: the current position in the buffer + * @from: the buffer to read from + * @available: the size of the buffer + * + * The simple_read_from_buffer() function reads up to @count bytes from the + * buffer @from at offset @ppos into the user space address starting at @to. + * + * On success, the number of bytes read is returned and the offset @ppos is + * advanced by this number, or negative value is returned on error. + **/ + return simple_read_from_buffer(ubuff, c, pos, kernel_buff, BUFF_LEN); +} + +static ssize_t debugfs_write(struct file *fp, const char __user *ubuff, size_t c, loff_t *pos) +{ + /** + * simple_write_to_buffer - copy data from user space to the buffer + * @to: the buffer to write to + * @available: the size of the buffer + * @ppos: the current position in the buffer + * @from: the user space buffer to read from + * @count: the maximum number of bytes to read + * + * The simple_write_to_buffer() function reads up to @count bytes from the user + * space address starting at @from into the buffer @to at offset @ppos. + * + * On success, the number of bytes written is returned and the offset @ppos is + * advanced by this number, or negative value is returned on error. + **/ + + if (c > BUFF_LEN) + return (-EINVAL); + + return simple_write_to_buffer(kernel_buff, BUFF_LEN, pos, ubuff, c); +} + +int debug_init(struct dentry **dir, struct dentry **file) +{ + /* func ptrs that perform various operations on the device, in this case char device, well not even */ + struct file_operations fops = { + .read = debugfs_read, + .write = debugfs_write + }; + /* omitted fields are initialized to NULL */ + + *dir = debugfs_create_dir("hello", NULL); + if (!*dir) + return (-ENODEV); + + /* regular file, read by user/group/other, write by user */ + *file = debugfs_create_file("magic", S_IFREG | S_IRUGO | S_IWUSR, *dir, &fileprv, &fops); + if (!*file) + printk("debugfs: error creating file\n"); + + return 0; +} + +int debug_destroy(struct dentry *dir, struct dentry *file) +{ + if (file) + debugfs_remove(file); + + if (dir) + debugfs_remove(dir); + + return 0; +} + @@ -0,0 +1,10 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +struct dentry; + +int debug_init(struct dentry **, struct dentry **); +int debug_destroy(struct dentry *, struct dentry *); + +#endif + @@ -0,0 +1,46 @@ +#include <linux/module.h> +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +/* used for kmalloc */ +#include <linux/slab.h> + +#include <debug.h> + +char *debugmsg = "Tesla coil is a hi freq transformer"; +struct dentry *debug_dir = NULL; +struct dentry *debug_file = NULL; + +/* __init is a hint that the func is only used at initialization time, then module + * loader drops the function after module is loaded making its memory available for other uses + */ +static int __init hello_init(void) +{ + int err = 0; + char *msg = (char *) kmalloc_array(128, sizeof(char), GFP_KERNEL /* kernel ram */); + + printk("module named hello inserted\n"); + strcpy(msg, "photon is the energy carrier particle for EM waves within light spectrum"); + printk("%s\n", msg); + kfree(msg); + + /* modifies passed in ptrs */ + err = debug_init(&debug_dir, &debug_file); + if (err) + printk("debugfs might not have been mounted\n"); + + return 0; +} + +static void __exit hello_exit(void) +{ + debug_destroy(debug_dir, debug_file); + printk("module named hello removed\n"); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_LICENSE("GPL"); + @@ -0,0 +1,7 @@ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +extern char *debugmsg; + +#endif + |