Homepage Wiki Forum Buy

Backport Kernel

From GNUBLIN

difficulty level prerequisites Gnublin Family
Gnublin logo advanced.png Kernel compiling, Toolchain All


New Hardware on old Kernel

This work is based on a buildroot Gnublin Linux. The procedure is analogous to a Debian distribution, as it is based on the same kernel.

Contents


small note: this is a empiric report, not a general instruction!


Buildroot

Starting with benbrensons version (http://code.google.com/p/gnublin-buildroot-git/) to build one Gnublin Linux and test. To avoid problems with the paths, it is recommended to select /opt/gnublin/buildroot as working directory instead of your home directory. The sourcecode for the external drivers to be built abd the sources for Compat-Wireless ( http://backports.wiki.kernel.org ) will be stored at opt/gnublin/src . All patches and paths refer to this layout. If the toolchain, the Kernel and the RootFS have been build an tested, you can / must configure the Kernel. Before we start, only a few comments to the kernel build system.


Kernel

Since kernel 2.6, a new configuration scheme is used that manages the various options that are necessary to build a flexible and modular operating system. The construction of drivers also benefits, as this also controls the dependencies between components and modules. There are basically two types of kernel modules to build externally in a separate directory or within the kernel tree. Both have advantages and disadvantages before. Since Backports be applied to different versions of the kernel, it is useful to manage the sources outside the individual core and only make the link on the build system at compile time.

A typical makefile for an external module looks like this:


obj-m := ext_kernel_modul.o

KERNELDIR     := /opt/gnublin/buildroot/output/build/linux-2.6.33/
CROSS_COMPILE := /opt/gnublin/buildroot/output/host/usr/bin/arm-linux-
PWD           := $(shell pwd)
ARCH          := arm

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

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

and it works well for embedded systems when toolchain and kernel directory are explicitly specified. Unlike many hardware manufacturers, the maintainer of the Compat-Wireless project have kept it, creating the best conditions for the creation of the necessary modules. The drawback lies in the fact that the dependencies that are usually dissolved by the kernel build system, now you have to edit yourself.

In Order that the translation works, you have to edit the Makefile:

KLIB:=          "/opt/gnublin/buildroot/output/build/linux-2.6.33"
ARCH:=          "arm" 
CROSS_COMPILE:= "/opt/gnublin/buildroot/output/host/usr/bin/arm-linux-"

A 'make clean' leads to some warnings about build options not set and to the problem mentioned above, since these can not be set explicitly in the usual way in the kernel configuration. A look at a typical config file shows the dilemma. Options are selected implicitly with the selection of individual modules, but we may compile them extenal in the new Version or even don't need them. After prolonged experiment three candidates remained, which were then added to the corresponding control file.

Add the following at the end of the Kconfig file in output/build/linux-2.6.33/arch/arm/mach-lpc313x/ :


   ................
   config NET_SCHED
	bool "Gnublin Extra Flag NET_SCHED"
	help
	  Say Y here if you are using extra flags

   config WIRELESS_EXT
	bool "Gnublin Extra Flag WIRELESS_EXT & LIBIPW"
	help
	  Say Y here if you are using extra flags

   config GENERIC_ATOMIC64
	bool "Gnublin Extra Flag GENERIC_ATOMIC64"
	help
	  Say Y here if you are using extra flags
   ...............


The new modules need the network driver scheduler, the Wireless Extensions (for iwconfig and wpa-tools) and 64-bit atomic operations. We meet the latter afterwards again.

You have to set the flags, if you want to add the drivers from the Compat library.

   SystemType ---> 
      Special settings  ---> 
	[*] Gnublin Extra Flag NET_SCHED                         
    	[*] Gnublin Extra Flag WIRELESS_EXT & LIBIPW                
    	[*] Gnublin Extra Flag GENERIC_ATOMIC64

There are other dependencies that occur during the build process, in part at the very end when the root file system is built, but more on that later. For the moment we leave the kernel build system and turn to the Compat-Wireless.

Compat-Wireless

First, download the stable release of http://www.kernel.org/pub/linux/kernel/projects/backports/2012/10/08/ in my case compat-drivers-2012-10-08-c.tar.gz, which raises the wireless subsystem to the level of 3.x. As already indicated above extract to /opt/gnublin/src and editing the Makefile. A first look into the source directory shows two important folders, and compat driver. The former is responsible for the backward compatibility, the latter will contain the current 3.x kernel driver. Here also the module that was ultimately the reason for all the trouble is found, the driver for the latest WLAN stick with the Ralink RT5370 chipset. The necessary firmware I had on my Debian development system , firmware-ralink.deb from the archives of http://backports.debian.org/debian-backports . This means that at least all the ingredients are available and it basically works, I have tried it in a VM with Debian6 x86 architecture already.


Now it's time for a first attempt to set the options in the buildroot directory and recompile:


make linux-menuconfig
make

The next problem! Because the layers must replaced with a 80211 from the backport, it must be translated as a module, the next round:

NetworkingSupport ---> 
    Wireless ---> 
	<M>   cfg80211 - wireless configuration API  

Next, and not at first glance trivial problem Syntax error in lib/atomic64.c. Since this problem not occurred in the preliminary study on the x86 architecture occurred here, the problem must lie on the ARM side!

//#include <asm/atomic.h>
#include <asm-generic/atomic64.h>

ARM processors have no 64-bit atomic operations, so you have to resort to a software solution with spinlocks. The involvement of arch / arm / ... there is still incomplete, the appropriate include file is included for the time manually.

The next 'make' then leads to an error-free translated and executable kernel.

We leave the buildroot directory and try the compat drivers translate. Thus emerging problems can be narrowed down better, we restrict ourselves to the desired WLAN USB driver.

scripts/driver-select rt2x00

The script selects all the necessary ingredients and creates a suitable configuration for the following make. The makefile for the compat drivers now make the changes described above:

#----------------------- GNUBLIN ------------------
KLIB_BUILD:=    /opt/gnublin/buildroot/output/build/linux-2.6.33
export KMODDIR?=       updates
KMODDIR_ARG:=   "INSTALL_MOD_DIR=$(KMODDIR)"
KMODPATH_ARG:=  "INSTALL_MOD_PATH=/opt/gnublin/buildroot/output/target"
export KLIB:=   /opt/gnublin/buildroot/output/build/linux-2.6.33
MAKE:= make ARCH=arm CROSS_COMPILE=/opt/gnublin/buildroot/output/host/usr/bin/arm-linux- 
#----------------------- GNUBLIN -----------------

Another error in relation to the atomic operations emerges! The same game as above, in the file net/mac80211/mesh_pathtbl.c insert the necessary additions.

#include <asm/atomic.h>

   static inline int atomic_add_unless(atomic_t *v, int a, int u) {
	return __atomic_add_unless(v, a, u);
 }

Immerhin jetzt läuft der Compiler durch, übrig bleiben drei Linker Warnings, crc_ccitt, cpufreq_cpu_get und cpufreq_cpu_put undefined! Die Ursache für die erste Warning ist ein noch fehlendes Kernel-Module, die letzten beiden sind modernen CPUs mit variabler Taktfrequenz geschuldet. Mit grep den Quelltext durchsucht und in compat/compat-3.1.c auskomentiert:

After all, the compiler now runs through, leaving only three linker warnings, crc_ccitt, cpufreq_cpu_get cpufreq_cpu_put and undefined! The cause of the first warning is still a lack of kernel modules, the last two are due to modern CPUs with variable frequency.Searched the source code using grep and commented out in compat/compat-3.1.c:

   .....
   /*
   unsigned int compat_cpufreq_quick_get_max(unsigned int cpu) 
   {
	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
	unsigned int ret_freq = 0;

	if (policy) {
		ret_freq = policy->max;
		cpufreq_cpu_put(policy);
	}
	return ret_freq;
   }
   .....
EXPORT_SYMBOL(compat_cpufreq_quick_get_max);
*/	

Activate the Kernel Module:

Library routines  --->
   <M> CRC-CCITT functions  

Recompile the kernel and drivers. If everything is accomplished without an error, a courageous 'make install-modules' and in /opt/gnublin/buildroot/output/target/lib/modules/2.6.33/updates/ are the new drivers.

Hotplug

Those who believe that it would be, you're wrong! Now you have to get the drivers running at the target platform. For this task we need Firmware. You found these at http://backports.debian.org/debian-backports. Save them at the target-directory as same as the drivers. Where exactly depends on the used hotplug system! How Hotplug works in detail is descriped in an own Article. Here only as much as we need for the first steps.

In the 2.6 Kernel there is an easy to handle hotplug interface. In /proc/sys/kernel/hotplug is the name of a script that is invoked at an event, the necessary information is passed by the command line and environment variables. By default, the name is /sbin/hotplug.

The kernel calls, when a USB device is dis/connected, /off/sbin/hotplug with the following arguments:

argv [0] = hotplug_path
argv [1] = "usb"
argv [2] = 0
HOME=/
PATH=/sbin:/bin:/usr/sbin:/usr/bin
ACTION=action
PRODUCT=idVendor/idProduct/bcdDevice
TYPE=device_class/device_subclass/device_protocol
INTERFACE=class/subclass/protocol
DEVFS=/proc/bus/usb
DEVICE=/proc/bus/usb/bus_number/device_number

To test it, we use the following simple script,

#! /bin/sh

env >> /dev/ttyS0

which redirects all outputs to the GNUBLIN console. Thus it is also called safe by the kernel, save the path in the proc file system.

echo /sbin/hotplug > /proc/sys/kernel/hotplug


After inserting the WLAN stick the USB subsystem reports the new device:

usb 1-1.4: New USB device found, idVendor=148f, idProduct=5370
usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1.4: Product: 802.11 n WLAN
usb 1-1.4: Manufacturer: Ralink
usb 1-1.4: SerialNumber: 1.0

An 'lsmod' on the other hand shows no loaded module and that is correctly, because for loading the modules the userland part of the hotplug system is responsible. So some handwork is necessary. Our script gives us back but a whole range of information:

DEVTYPE=usb_device
SUBSYSTEM=usb
DEVPATH=/devices/platform/lpc-ehci.0/usb1/1-1/1-1.4
DEVNUM=005
MINOR=4
ACTION=add
BUSNUM=001
MAJOR=189
DEVNAME=bus/usb/001/005
DEVICE=/proc/bus/usb/001/005
PRODUCT=148f/5370/101

A 'modprobe rt2800usb' loads the driver along with the necessary modules. Activating swapspace on a 8MB Board is necessary! Nevertheless, the charge is due to the low memory very bumpy, so use a small and compact Kernel as possible and disable unneeded services.

'lsmod' then shows the modules loaded.

Module                  Size  Used by    Not tainted
rt2800usb              12116  0 
rt2800lib              48139  1 rt2800usb
crc_ccitt               1031  1 rt2800lib
rt2x00usb               7095  1 rt2800usb
rt2x00lib              29602  3 rt2800usb,rt2800lib,rt2x00usb
mac80211              224997  3 rt2800lib,rt2x00usb,rt2x00lib
cfg80211              151534  2 rt2x00lib,mac80211
compat                 19410  4 rt2800usb,rt2x00lib,mac80211,cfg80211
led_class               2091  2 rt2x00lib,compat

A new device called wlan0 is present, a 'ifconfig wlan0 192.168.6.99' requires a firmware upload:

......
SUBSYSTEM=firmware
DEVPATH=/devices/platform/lpc-ehci.0/usb1/1-1/1-1.4/1-1.4:1.0/firmware/1-1.4:1.0
FIRMWARE=rt2870.bin
......

Who wants or must build a very compact system, may use the example script from the Kernel-Documentation (linux-2.6.33/Documentation/firmware-class/hotplug-script). Before doing so, you must create the /lib/firmware directory and save the rt2xxx.bin files there.

# Simple hotplug script sample:
# 
# Both $DEVPATH and $FIRMWARE are already provided in the environment.

HOTPLUG_FW_DIR=/lib/firmware/

echo 1 > /sys/$DEVPATH/loading
cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
echo 0 > /sys/$DEVPATH/loading

# To cancel the load in case of error:
#
#	echo -1 > /sys/$DEVPATH/loading
#

The door to a unencrypted WLAN is open to us now. For a final, especially automatic solution you should better use one of the two final userland hotplug systems. I chose mdev because of the low memory requirements and the simplicity of it and enabled it in the BusyBox Buildroot configuration .

mdev

Automatically to the WLAN .......

We use mdev as hotplug-script and activate the hotplug at the system-startscript /etc/init.d/rcS :

#!/bin/sh

# Init hotplug interface 
echo /sbin/mdev > /proc/sys/kernel/hotplug

# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do
...........

The configuration is in the file / etc / mdev.conf:

$MODALIAS=.*    0:0 0660 @modprobe "$MODALIAS" 
wlan[0-9]*      0:0 0660 */etc/mdev.wlan

The first calls 'modprobe' and loads the necessary modules. If all goes well and the USB device is a wireless device, the matching network interface wlan0 exists and as an action, the script will run mdev.wlan:

#!/bin/sh
LOG="logger -p user.info -t mdev-wlan"
WARN="logger -p user.warn -t mdev-wlan"

case "$ACTION" in
        add | "" )
                if [ -s /etc/wpa_supplicant.conf ]; then
                        $LOG "trying to bring $MDEV up"
                        wpa_supplicant -B -Dwext -i $MDEV -c /etc/wpa_supplicant.conf
                        ifup $MDEV
                else
                        $WARN "/etc/wpa_supplicant.conf missing or empty, not trying to bring $MDEV up"
                fi
                ;;
 	remove )
		$LOG "trying to bring $MDEV down"
		ifdown $MDEV
                killall wpa_supplicant
		;;
esac       
          

Now save the configuration for the WLAN to /etc/wpa_supplicant.conf :

# home network; allow all valid ciphers
network={
    ssid="FLAN6"
    key_mgmt=NONE
#--------- WPA -----------------
#   key_mgmt=WPA-PSK
#   psk="very secret passphrase"

}

activate wlan0 for 'ifup' and enter it to /etc/network/interfaces:

# cat /etc/network/interfaces 
# Configure Loopback
auto lo
iface lo inet loopback
iface wlan0 inet dhcp

Connect the WLAN USB Stick and the rest should work automatically:

usb 1-1.2: new high speed USB device using lpc-ehci and address 3
usb 1-1.2: New USB device found, idVendor=148f, idProduct=5370
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1.2: Product: 802.11 n WLAN
usb 1-1.2: Manufacturer: Ralink
usb 1-1.2: SerialNumber: 1.0
Compat-drivers backport release: compat-drivers-2012-10-08-c
Backport based on linux-next.git next-20121008
compat.git: linux-next.git
cfg80211: Calling CRDA to update world regulatory domain
usb 1-1.2: reset high speed USB device using lpc-ehci and address 3
Registered led device: rt2800usb-phy0::radio
Registered led device: rt2800usb-phy0::assoc
Registered led device: rt2800usb-phy0::quality
usbcore: registered new interface driver rt2800usb
rt2800usb 1-1.2:1.0: firmware: requesting rt2870.bin
wlan0: authenticate with 90:f6:52:c5:0c:58
wlan0: send auth to 90:f6:52:c5:0c:58 (try 1/3)
wlan0: authenticated
wlan0: associate with 90:f6:52:c5:0c:58 (try 1/3)
wlan0: RX AssocResp from 90:f6:52:c5:0c:58 (capab=0x421 status=0 aid=1)
wlan0: associated

# lsmod
Module                  Size  Used by    Not tainted
rt2800usb              12116  0 
rt2800lib              48147  1 rt2800usb
crc_ccitt               1031  1 rt2800lib
rt2x00usb               7103  1 rt2800usb
rt2x00lib              29634  3 rt2800usb,rt2800lib,rt2x00usb
mac80211              225585  3 rt2800lib,rt2x00usb,rt2x00lib
cfg80211              151782  2 rt2x00lib,mac80211
compat                 19454  4 rt2800usb,rt2x00lib,mac80211,cfg80211
led_class               2091  2 rt2x00lib,compat

#ifconfig
wlan0     Link encap:Ethernet  HWaddr 7C:DD:90:0B:B0:FB
          inet addr:192.168.6.100  Bcast:192.168.6.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:29 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:10332 (10.0 KiB)  TX bytes:696 (696.0 B)

Cennection is up !

That's it!

recipe Buildroot

Patches and more ....

All patches apply to the following directory structure:

  /opt/gnublin/buildroot/....
  /opt/gnublin/src/compat-drivers-2012-10-08-c/....

and were created with 'diff -uNr original new' in /opt/gnublin

  500-arch-lpc313x-Kconfig.patch   
  501-lib-atomic64.patch           
  502-compat-net-mac80211.patch 
  503-compat-compat-3.1.patch 
  504-compat-makefile.patch 

apply the patches in the /opt/gnublin: 'patch -p0 < 50.....'

alternatively in .../buildroot : 'patch -p1 < 50.....'

or .../src/compat-drivers-2012-10-08-c : 'patch -p2 < 50.....'

recipeDebian Gnublin

Apply the whole to the current Debian Distro.

As a basis you need the Debian Gnublin build system as described in the article Gnublin Distribution described.

Best install outside of the home directory, with compat-drivers-2012-10-08-c.tar.gz from http://www.kernel.org/pub/linux/kernel/projects/backports/2012/10/08/ and the necessary patches.

  600-arch-lpc313x-Kconfig.patch   
  601-lib-atomic64.patch           
  602-compat-net-mac80211.patch 
  603-compat-compat-3.1.patch 
  604-compat-makefile.patch 

My directory looks like this:

filou@moave:/opt/debian/gnublin$ ls -l
insgesamt 40
-rw-r--r--  1 filou filou  623 10. Jan 19:22 600-arch-lpc313x-Kconfig.patch
-rw-r--r--  1 filou filou  373 10. Jan 19:23 601-lib-atomic64.patch
-rw-r--r--  1 filou filou  461 10. Jan 19:23 602-compat-net-mac80211.patch
-rw-r--r--  1 filou filou  475 10. Jan 19:23 603-compat-compat-3.1.patch
-rw-r--r--  1 filou filou 2461 10. Jan 19:26 604-compat-makefile.patch
drwxr-xr-x 34 filou filou 4096  6. Jan 17:36 busybox-1.20.2
drwxr-xr-x 15 filou filou 4096  5. Jan 19:18 compat-drivers-2012-10-08-c
drwxr-xr-x 14 filou filou 4096  5. Jan 19:01 lpc3131

Then switch to the Kernel-directory and apply the patches:


cd /opt/debian/gnublin/lpc3131/kernel/linux-2.6.33-lpc313x
patch -p0 < /opt/debian/gnublin/600-arch-lpc313x-Kconfig.patch
patch -p0 < /opt/debian/gnublin/601-lib-atomic64.patch

Same in the Compat-drivers-directory:


cd /opt/debian/gnublin/compat-drivers-2012-10-08-c
patch -p0 < /opt/debian/gnublin/602-compat-net-mac80211.patch
patch -p0 < /opt/debian/gnublin/603-compat-compat-3.1.patch
patch -p0 < /opt/debian/gnublin/604-compat-makefile.patch


If other paths are used, adjust the Makefile!

And continues as in the Buildroot-Kernel above, set the options and modules. Delete the .stamp-kernel file and recompile the Kernel with make. Next the drivers in the directory /opt/debian/gnublin/compat-drivers-2012-10-08-c:


make clean
scripts/driver-select rt2x00
make

Insert the SD-card in your PC and apply the necessary changes. You need temporary root-rights! My SD-cards My SD card is recognized as 'sdc' by the kernel, Please edit your commands correspondingly!


su
mount -t ext2 /dev/sdc1 /mnt/gnublin
cd /opt/debian/gnublin/lpc3131/output
cp -a 2.6.33-g0642480* /mnt/gnublin/lib/modules
cp -a zImage /mnt/gnublin
cd /opt/debian/gnublin/compat-drivers-2012-10-08-c
make install-modules
chown -R root:root /mnt/gnublin/lib/modules
cp -a /lib/firmware/rt2* /mnt/gnublin/lib/firmware/
umount /dev/sdc1

Now you can boot GNUBLIN from the modified card. If the hotplug is adjusted as in the Buildroot kernel, everything works automatically: USB device detect, load drivers, firmware load, sign on wireless, and get IP address via DHCP:

Compat-drivers backport release: compat-drivers-2012-10-08-c
Backport based on linux-next.git next-20121008
compat.git: linux-next.git
cfg80211: Calling CRDA to update world regulatory domain
usb 1-1.2: reset high speed USB device using lpc-ehci and address 3
Registered led device: rt2800usb-phy0::radio
Registered led device: rt2800usb-phy0::assoc
Registered led device: rt2800usb-phy0::quality
usbcore: registered new interface driver rt2800usb
rt2800usb 1-1.2:1.0: firmware: requesting rt2870.bin
ADDRCONF(NETDEV_UP): wlan0: link is not ready
wlan0: authenticate with 90:f6:52:c5:0c:58
wlan0: send auth to 90:f6:52:c5:0c:58 (try 1/3)
wlan0: authenticated
wlan0: associate with 90:f6:52:c5:0c:58 (try 1/3)
wlan0: RX AssocResp from 90:f6:52:c5:0c:58 (capab=0x421 status=0 aid=1)
wlan0: associated
ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready

ON AIR

TODO

recipe mdev

In other languages