6

My Raspberry Pi currently runs 3.6.11+ #538 (obtained from uname -a), which may be the source of my issues. I'm starting to write a kernel module using the following "Hello World" code:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>

static int __init gotemp_init(void)
{
    printk(KERN_INFO "Hello from the kernel!\n");
    return 0;
} 

static void __exit gotemp_exit(void)
{
}

module_init(gotemp_init);
module_exit(gotemp_exit);

MODULE_AUTHOR("My name here");
MODULE_DESCRIPTION("Simple driver");
MODULE_LICENSE("GPL");

And a make file:

obj-m   := hello.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)

all:
    $(MAKE) -C $(KERNELDIR) M=$(PWD)

clean:
    rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c

Source slides/demo code here

I ran into an issue that 3.6.11+'s Linux headers were not released nor installable via apt-get, but I did find with Google that there were .deb files with the needed headers found here. Kernel modules obviously cannot be compiled without the kernel headers, so this seems to have been a fix.

Until I run:

insmod ./hello.ko

which spits out a segmentation fault. I read that is can be due to a mismatch of the running kernel and the kenel compiled against, but as far as I know, the two match up. Is there something I am missing?

I attempted to download the latest kernel from github.com/raspberrypi/linux and build from that. The kernel version I got from git fetch git@github.com:raspberrypi/linux rpi-3.6.y:refs/remotes/origin/rpi-3.6.y ended up being 3.6.11 #1. I attempted to compile and run with the new kernel and ended up with:

Error: could not insert module hello.ko: Invalid module format.

I know I want to run with 3.6 and not 3.4, because according to Linux Programming, <3.4 has bad drivers for USB. I need the working version of these drivers in 3.6.

After rebuilding the kernel again, I finally have the module running, but I don't know what version of the kernel I am running, ref. How to tell if I am running the latest version of the raspbian kernel.

It seems that by building the kernel from the repository myself, I don't get the benefit of knowing exactly what version of the kernel I am running, except that it is the bleeding edge of the 3.6.11+ branch according to https://raspberrypi.stackexchange.com/a/10432/10085. Yay?

Nielsvh
  • 203
  • 1
  • 11
  • You can catch these errors somehow- I forgot how, hence the comment instead of answer. Segmentation fault can mean anything and should never happen. When they do its a very specific error that needs to be debugged. Sometimes its corruption, permissions or something else. – Piotr Kula Oct 24 '13 at 13:57

1 Answers1

3

Could you be more specific on the kernel version (use uname -a, some of the 3.6.11+ kernels are not compatible with each other, for example #538 and onwards do not match earlier revisions).

The code you have there seems fine, but I think the build instruction for all needs to have modules after it, e.g. $(MAKE) -C $(KERNELDIR) M=$(PWD) modules.

For reference the makefile I use for doing this is as follows:

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := ledborg.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:    driver

rebuild:    clean driver

clean:
    rm -rf .tmp_versions
    rm -f .*.cmd
    rm -f Module.symvers
    rm -f modules.order
    rm -f *.ko
    rm -f *.o
    rm -f *.mod.*
    rm -f ../ledborg.ko

driver:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    cp ledborg.ko ../ledborg.ko
endif

it does a couple of extra bits, but I think you may also need the conditional lines ifneq ($(KERNELRELEASE),), else, and endif in the same places (the build gets double-invoked for kernel modules...)

If you are using the latest kernel (sudo apt-get update followed by sudo apt-get upgrade) then you should be able to use the following to pull the correct headers and symbol file from the version control system used to generate the builds in the first place:

cd /usr/src
wget -O rpi-`uname -r`.tar.gz https://github.com/raspberrypi/linux/tarball/rpi-3.6.y
rm -rf raspberrypi-*
tar xzf rpi-`uname -r`.tar.gz
cd raspberrypi-*
KSRC=`pwd`
pushd /lib/modules/`uname -r`
rm source
rm build
ln -s ${KSRC} source
ln -s ${KSRC} build
popd
pushd /usr/src
rm linux-`uname -r`
rm linux
ln -s ${KSRC} linux-`uname -r`
ln -s ${KSRC} linux
popd
zcat /proc/config.gz > .config
make oldconfig
make modules_prepare
wget -O Module.symvers https://github.com/raspberrypi/firmware/raw/master/extra/Module.symvers

I have used this for building the LedBorg kernel drivers when they release new versions, I have made a script out of the commands that you can download and run using

cd ~
wget -O get-kernel-source.sh http://piborg.org/downloads/get-kernel-source.txt
chmod +x get-kernel-source.sh
sudo ~/get-kernel-source.sh

which should leave you with a script to run again if you update the kernel and need to rebuild the kernel module.

PiBorg
  • 1,497
  • 10
  • 11
  • I was looking around for how one even generates the headers, but most documentation skips over generating them and just tells you to get them from the distribution repo. – Nielsvh Oct 24 '13 at 15:12
  • 1
    The thing is that it works the other way around, the kernel itself is built using those headers, the idea is that your module should be built against the exact same headers. – PiBorg Oct 24 '13 at 20:00
  • I should have been more specific. 'Extracting the headers' would have been a better phrasing, since I have the release code for the kernel. – Nielsvh Oct 24 '13 at 20:34
  • Welp, now I have 3.6.11+ #1 instead of #358 and I get the error: "Error: could not insert module hello.ko: Invalid module format" – Nielsvh Oct 28 '13 at 19:09
  • #1 sounds odd, not to mention it implies an old copy, could you show the whole version details from uname -a... – PiBorg Oct 29 '13 at 09:15
  • The date on the build may help, but I guess the image from raspberrypi.org is older then the development branch, consequently the Module.symvers is more recent. The error about Invalid module format is usually because the Module.symvers the kernel generated during the build is not the same as the one used to build the driver. – PiBorg Oct 29 '13 at 18:34
  • Cool, so if I were to do a checkout of the commit at which my build was generated, I should have the same headers and modules, right? I should have a stable system? – Nielsvh Oct 29 '13 at 20:58
  • That is the general idea :) – PiBorg Oct 29 '13 at 22:37
  • I may have done goofed with my last kernel build and misplaced the modules I built. I'm currently rebuilding the kernel after the last one killed my USB keyboard and mouse inputs. – Nielsvh Oct 29 '13 at 22:47
  • OK. I built the kernel following the instructions here and rebuilt the entire kernel from the git repo (git fetch git@github:raspberrypi/linux rpi-3.6.y:refs/remotes/origin/rpi-3.6.y). After everything is done I get the following output for uname -a: "Linux raspberrypi 3.6.11+ #1 PREEMP Wed Oct 30 02:19:13 UTC 2013 armv6l GNU/Linux". git log shows 10bc58289 as the last commit, so I have the latest code, according to the github repo. – Nielsvh Oct 30 '13 at 18:58
  • But I don't get segfaults or invalid module errors... It now works, but I don't know if I have the latest version of the kernel. – Nielsvh Oct 30 '13 at 19:16
  • Since you have built the latest code in the repository it is probably more recent then the version people have using sudo apt-get upgrade, you have a really new version :) – PiBorg Oct 31 '13 at 15:47
  • Yay bleeding edge... – Nielsvh Oct 31 '13 at 16:08