I have a Raspberry Pi 2 "model B" (the only rpi2 model) and I wanted to get
this usb wifi driver,
compiled and installed for a linux kernel installed by the "rpi-update
" tool.
Unlike a packaged kernel provided by a debian-based linux distro which you may
be using, for example "linux-image-raspi2
" which is available in Ubuntu Mate
15.10 armhf (used by the Ubuntu Mate sdcard image for the rpi2) and for which there
is a corresponding "linux-headers-raspi2
" which provides all the bits needed
to compile an out-of-tree module for use with that kernel, the situation for
kernels installed by rpi-update
is a bit more complicated. It looks like this
process works for rpi-update
installed kernels for all Raspberry Pi models,
so that's nice.
You'll need curl
and build-essential
installed.
$ sudo apt-get install curl build-essential
The rpi-update
tool downloads (and checks and copies) updated firmware files
and compiled linux kernels into the /boot
partition. The kernels are kernel.img
and kernel7.img
- the "7" variant is for the Rasberry Pi 2, which has a processor
which supports the ARMv7 instruction set, whereas all other Raspberry Pi models
have a processor which supports the ARMv6 instruction set. The runtime-loadable
kernel modules which are installed along with the kernel are in folders in
/lib/modules
. I currently have:
$ ls -l /lib/modules
total 16
drwxr-xr-x 3 root root 4096 Feb 16 17:04 4.1.17+
drwxr-xr-x 3 root root 4096 Feb 16 20:54 4.1.17-v7+
drwxr-xr-x 3 root root 4096 Feb 21 13:57 4.1.18+
drwxr-xr-x 3 root root 4096 Feb 21 21:07 4.1.18-v7+
The kernel I'm currently running on this rpi2 is 4.1.18-v7+
(the "-v7" variant
is for the "7" kernel). Once you've rebooted to run the most recent kernel
installed by rpi-update
, there's no point in keeping the old module dirs
(4.1.17+
and 4.1.17-v7+
in my case) as the old kernels they correspond to
are overwritten and gone. You can get the version of the currently running kernel
with "uname -r
" (and you can also see it at the beginning of the kernel log
with "dmesg | head
").
So we know the kernel that's running, and where its module dir is. We now need
the kernel source tree and some other outputs of the build that produced this
running kernel. The secret is the Hexxeh/rpi-firmware
repo on github, and the
file /boot/.firmware_revision
which contains a commit hash from that repo.
(The raspberrypi/firmware
repo on github is very similar, but arranged a bit
differently and has different commit hashes. The rpi-update
I have seems to
use the Hexxeh repo.)
$ cat /boot/.firmware_revision
68febe187617906637e0ac71b0c8b8f581f10078
Now we can get the commit of the raspberrypi/linux
repo which was used to build the
kernel and modules:
$ FIRMWARE_REV=68febe187617906637e0ac71b0c8b8f581f10078
$ curl -L https://github.com/Hexxeh/rpi-firmware/raw/${FIRMWARE_REV}/git_hash
2f9dd6a9a79c7d88068e65e98d3a159ecb7a0a9b
$ KERNEL_REV=2f9dd6a9a79c7d88068e65e98d3a159ecb7a0a9b
We also need one other file, Module.symvers
, which also has a "7" variant which
corresponds to the "7" version of the kernel, for the rpi2. (If you don't have a
rpi2, you should be using the non-"7" variants throughout these steps.)
$ curl -L https://github.com/Hexxeh/rpi-firmware/raw/${FIRMWARE_REV}/Module7.symvers >Module7.symvers
Cloning a linux kernel git repository on an sdcard in a rpi takes quite a while, but all we want is the checkout from a particular revision, which we can get in a tarball from github:
$ curl -L https://github.com/raspberrypi/linux/archive/${KERNEL_REV}.tar.gz >rpi-linux.tar.gz
... curl progress ...
Now, assuming you ran the previous commands as a normal user in your home directory, switch to root and do the following:
$ sudo -s
[sudo] password ...:
# cd /usr/src
# mkdir rpi-linux
# cd rpi-linux
# tar --strip-components 1 -xf ${HOME}/rpi-linux.tar.gz
# ls
arch CREDITS drivers include Kbuild lib mm REPORTING-BUGS security usr
block crypto firmware init Kconfig MAINTAINERS net samples sound virt
COPYING Documentation fs ipc kernel Makefile README scripts tools
Now add .config
(from the running kernel) and Module.symvers
:
# modprobe configs
# gunzip -c /proc/config.gz >.config
# cp $HOME/Module7.symvers Module.symvers
Finally run make modules_prepare
and link into the appropriate modules dir:
# make modules_prepare
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
... a minute or two ...
HOSTCC scripts/recordmcount
HOSTCC scripts/sortextable
# ln -sv /usr/src/rpi-linux /lib/modules/$(uname -r)/build
?‘/lib/modules/4.1.18-v7+/build?’ -> ?‘/usr/src/rpi-linux?’
That should be it, now I can build this out-of-tree module. (Well this
particular one also notes in the README that you have to edit the Makefile
just
to toggle CONFIG_PLATFORM_I386_PC
and CONFIG_PLATFORM_ARM_RPI
.)
# cd /usr/src/rtl8812AU_8821AU_linux
# make
make ARCH=arm CROSS_COMPILE= -C /lib/modules/4.1.18-v7+/build M=/usr/src/rtl8812AU_8821AU_linux modules
make[1]: Entering directory '/usr/src/rpi-linux'
CC [M] /usr/src/rtl8812AU_8821AU_linux/core/rtw_cmd.o
... a few minutes ...
MODPOST 1 modules
CC /usr/src/rtl8812AU_8821AU_linux/8812au.mod.o
LD [M] /usr/src/rtl8812AU_8821AU_linux/8812au.ko
make[1]: Leaving directory '/usr/src/rpi-linux'
# make install
install -p -m 644 8812au.ko /lib/modules/4.1.18-v7+/kernel/drivers/net/wireless/
/sbin/depmod -a 4.1.18-v7+
# modprobe 8812au
# lsmod | grep 8812au
8812au 958764 0
cfg80211 389253 1 8812au