Today, I had to compile a custom kernel driver for Ubuntu, and it took me quite a while to do. There are a lot of guides out there, but many of them don’t seem to show the right way, or they do it one very specific way. Fortunately, thanks to this person, I’ve figured out an easy way to do this which doesn’t involve re-compiling the entire kernel.
- Install the dependencies you need to build(build-essential will be pulled in automatically on Ubuntu, you may need to specify it if you’re using Debian): sudo apt-get install dpkg-source
- Install whatever kernel you want to use. If you’re running the kernel you want to use, skip this step. For example, on Ubuntu 12.04, you can install an image as such: sudo apt-get install linux-image-3.5.0-47-generic
- Install your kernel headers if you have not done so: sudo apt-get install linux-headers-`uname -r`
- Get the source of the kernel. This is going to be quite large. Also, you don’t have to do this as sudo. apt-get source linux-image-`uname -r`
- Go to the directory that this source is in; for default Ubuntu installations, this will be: cd ./linux-3.2.0
- Prepare the workspace: make oldconfig && make prepare
- Copy the Module.symvers file from your currently running kernel into the build directory. This is VERY IMPORTANT, as otherwise you will be unable to properly build and install the module. This may lead to errors such as “no symbol table for module_layout” in dmesg when you attempt to load the module. cp /usr/src/linux-headers-`uname -r`/Module.symvers .
- Edit whatever module you want. In this example, I’m going to edit the ftdi_sio driver so that whenever the driver loads it will print out an awesome message. In the ftdi_init function, I simply added a line to print when the module is loaded: printk( “RM5248 IS AWESOME” );
- Make the module. Since we don’t want to rebuild the entire kernel, we just have to specify which driver to build. Do it as such: make M=drivers/serial/usb/
Using M=<directory> here is important; it makes sure that your Module.symvers won’t be overwritten
- Insert the module into the kernel to test it out: sudo insmod drivers/usb/serial/ftdi_sio.ko
If you get an error “Invalid module format” you’ve done something wrong, probably with the Module.symvers file. On my system, this fails the first time with “Unkown symbol in module” – you should be able to fix this by doing: sudo depmod -a
- Once you’re happy with your kernel module, put it into its permanent location: sudo cp drivers/usb/serial/ftdi_sio.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial/ftdi_sio.ko