Reconfiguring Linux kernel and adding drivers into Galileo’s Linux image

Table of contents:

How to determine which driver you need How to reconfigure the kernel and build the driver Prerequisites Configuration Building How to install the driver Additional information

This one got quite long as I’ve tried to make it as accessible as possible to people without Yocto experience. Oh well :) Use the TOC above to jump to specific pieces.

There have been several topics in the Intel Makers community asking for additional drivers or enabling support for specific features/hardware in the Linux kernel for Galileo’s Linux image. Thanks to Yocto framework, that is rather simple and I’m going to describe the process in this post, using USB Wi-Fi dongle as an example.

In general, we’ll be talking about so-called “in tree” drivers, i.e. those supported by Linux kernel out of the box. There may be cases, when the hardware you have isn’t [yet] supported by Linux kernel directly and manufacturer provides drivers separately, in such a case the process will be different and generally the same as for any other software you install from sources (compile, install, run), I’m not covering it here.

The idea itself is not specific to Galileo, you can use it with any Yocto-based Linux. Specific instructions and screenshots below are based on Yocto 1.4.2 and Galileo (actually Quark) Board Support package version 1.0.1 (the latest one at the time of writing) and can be used as-is with them. The same goes for BSP 1.0.0, which is what the latest officially released Galileo SD card Linux image is based upon right now.

So let’s get started.

Let’s assume you have an existing SD card with Linux image on it and a Wi-Fi dongle you want to use with Galileo, so you connect it and the only thing you see – on the serial console if you’re connected using serial cable or in the kernel log if you’re connected via SSH – is:

root@quark:~# dmesg |tail -1
[  580.500164] usb 2-1: new high-speed USB device number 3 using ehci-pci

That's a clear indication that the driver you need is at least not loaded or maybe not even present in the image.

How to determine which driver you need

There are at least two approaches you can use to determine which driver (kernel module) you need:

  1. By connecting your device to a computer with a "full-blown" Linux distro (Debian, Ubuntu, openSUSE, you name it) and watching the dmesg output. Desktop and server distros typically have many drivers enabled by default and mechanisms for loading them automatically when supported hardware is connected. When the driver loads and initializes the hardware, you usually see some output with kernel module name in the kernel log.
  2. By using lsusb or lspci utilities on Galileo to find out the Device ID and then looking it up using Google or specialized resources like Web LKDDb.

After you've obtained the kernel module name, you'll need to determine which kernel configuration option enables it. LKDDb is very nice in this regard, because it gives you that right away, along with the module name.

I use the second approach most of the time and the first place I check is namely LKDDb + Google if something is unclear there.

Let's see how exactly does that work. As long as this is a USB device, use lsusb to find the ID:

root@quark:~# lsusb
Bus 002 Device 003: ID 0bda:8171
Bus 001 Device 001: ID 1d6b:0001
Bus 002 Device 001: ID 1d6b:0002

You can use that command before and after connecting the device to filter out irrelevant entries. In our case the full Device ID is 0bda:8171. It's comprised of Vendor ID (0bda) and Product ID (8171) parts.

Use the Google custom search form on the LKDDb site to find the Product ID and then select the right Vendor. Make sure to narrow down the search to the LKDDb web site, otherwise it will be harder for you to filter relevant information out.

LKDDb search string example

Our search returns four results and we need the fourth one, because the first and the third ones are irrelevant due to different Vendor ID (10ec), the second one is also off the table after looking at the entry on detail - it's for 2.6.x Linux kernels ("found in Linux kernels: 2.6.31–2.6.36") and Galileo currently has kernel version 3.8.7. See screenshots below for an illustration.

Search results

LKDDb_search_result_2

Looking at the fourth search result in detail we see that we need a module called r8712u and it's enabled using CONFIG_R8712U kernel configuration option. Let's now see how to get it built.

How to reconfigure the kernel and build the driver

Prerequisites


You'll need a Linux system with Quark BSP unpacked and prepared for building per the BSP Build Guide. I'm not covering the details of preparing the environment here as BSP Build Guide is generally sufficient + there are articles on this elsewhere. Let me know in comments if you want an article on this :) You can use a VM appliance I've build using SUSE Studio to make the setup a bit easier.

Note that you need to create the kernel config at least once after initializing the build environment, to have a base for your changes. You don't need to build a full OS image if your only goal is to add the driver or change an option, you can simply build the kernel and modules and add them to an existing image you have on SD card. Assuming your Yocto environment is in /tmp/meta-clanton_v1.0.1, run these commands:

cd /tmp/meta-clanton_v1.0.1
source poky/oe-init-build-env yocto_build/
bitbake -c configure linux-yocto-clanton

That will build a bunch of utilities, fetch and configure Linux kernel sources.

Configuration


After it's done, let's enable our driver using standard kernel configuration process. The default way to do this is to run

bitbake -c menuconfig linux-yocto-clanton

That should open up a separate console window with kernel's graphical configuration utility. However on some distros (e.g. the one I'm using, openSUSE 12.3) that may not work, so there's an alternative, which is pretty much the same, but slightly longer in invocation:

bitbake -c devshell linux-yocto-clanton

and then in the devshell window that opens up:

make nconfig

You'll see something like this:

Kernel_config_tool_1

And we now need to enable the respective config option in this hierarchical menu. The simplest way to find out where it is located is to use search (F8 key):

Kernel_config_tool_2

which will return this information about the item's location, current state and dependencies:

Kernel_config_tool_3

Go to Device Drivers -> Staging drivers, highlight the "RealTek RTL8712U <...>" entry and hit Enter key, that will add a "M" in front of the option, which means this driver will be built as a shared module. The utility will also enable all the necessary dependencies automatically.

Kernel_config_tool_4

Now, save the config with the default name by hitting F6 and Enter. After that exit the configuration utility by hitting F9 and close the devshell window with Ctrl+D. If you've used menuconfig, the keys may be a bit different and you won't have a devshell to close.

Building


Now build the kernel and kernel modules by running

bitbake linux-yocto-clanton

After it's finished, you'll have the module in a form of *.ipk package in /tmp/meta-clanton_v1.0.1/yocto_build/tmp/deploy/ipk/clanton/kernel-module-r8712u_3.8-r0_clanton.ipk and the kernel itself in /tmp/meta-clanton_v1.0.1/yocto_build/tmp/deploy/image/bzImage.

How to install the driver

Boot the board, copy the ipk file with the kernel module there using scp utility (PuTTY, WinSCP and so on for Windows) to e.g /tmp dir:

scp /tmp/meta-clanton_v1.0.0/yocto_build/tmp/deploy/ipk/kernel-module-r8712u_3.8-r0_clanton.ipk root@192.168.1.2:/tmp

and install it using opkg:

root@quark:~# opkg install /tmp/kernel-module-r8712u_3.8-r0_clanton.ipk 
Installing kernel-module-r8712u (3.8-r0) to root...
Configuring kernel-module-r8712u.

Load the module with

modprobe r8712u

Then connect the USB dongle and verify that dmesg output now contains meaningful information about the device being recognized. This is Wi-Fi device, so it also requires a firmware blob I haven't bothered to download yet, thus that "firmware request failed", but as you can see the driver is functioning and correctly initializes the HW and reports its MAC address:

root@quark:~# dmesg |tail
[   64.694928] usbcore: registered new interface driver r8712u
[   72.290164] usb 2-1: new high-speed USB device number 2 using ehci-pci
[   72.450979] r8712u: Staging version
[   72.454822] r8712u: register rtl8712_netdev_ops to netdev_ops
[   72.460714] r8712u: USB_SPEED_HIGH with 4 endpoints
[   72.478649] r8712u: Boot from EFUSE: Autoload OK
[   73.203898] r8712u: CustomerID = 0x0000
[   73.207813] r8712u: MAC Address from efuse = 08:10:76:0d:bd:45
[   73.213771] r8712u: Loading firmware from "rtlwifi/rtl8712u.bin"
[   73.232265] r8712u: Firmware request failed

By the way, FWIW some further experimenting revealed that this particular driver fully deserves its "staging" status in this kernel version and doesn't work well on Galileo - crashes from time to time and the behavior is generally unstable. So I went on and built a driver (using absolutely the same approach) for my other dongle, based on some Ralink chipset. It worked perfectly and that's what I use day to day.

Note also that if you change something beyond just a simple module build - you may need to replace your kernel (bzImage file) in the SD card root with the one you've just built. E.g. in this particular case we've also enabled two options as dependencies for the driver, so it's worth doing that. Make sure to back up the existing file before replacing.

Additional information

This all is based on standard Yocto features and you can read more on this in the Yocto manuals here and here

You can also make these changes more permanent by using Yocto layers, recipes and so called configuration fragments. This can also help you to introduce your changes faster than the above manual ad-hoc way, provided you have the environment ready and know exactly which kernel config options (with dependencies) you need to enable - you can simply create a config fragment and let Yocto merge it for you.

You can see examples of this approach in my Yocto layer at https://github.com/alext-mkrs/meta-alex-galileo, more specifically this and this recipes.

9 Replies to “Reconfiguring Linux kernel and adding drivers into Galileo’s Linux image”

  1. You’ve all of my esteem!
    This post really helped me in putting some order in my Galileo build pipeline… it should be a sticky post in the forum ! :)

    thanks a lot

  2. I have been trying to develop a driver, information in this blog was a much needed one. Saves lot of time in build n other activities.
    Good one AlexT

  3. I’m trying something similar on an ARM platform, that is including the driver for the OMAP4 ISS (built in / staging). I can see from menuconfig and the fact that the object files are in the build directory that the module is compiling, however nothing relevant ends up in the deploy/rpm folder and the module isn’t listed on the target under /lib/modules/3.17.8-custom/modules.builtin. any ideas / hints on what I might be missing?

  4. Hi Michael,
    Theoretically, the modules should land under deploy/rpm/{$MACHINE} directory by default, however Yocto is quite flexible, maybe you have some settings altering that (though I can’t think of anything specific to check for OTMH). Maybe just a simple “find -name ‘*modulename*'” would find it?

  5. Hi
    I am trying to activate piTFT display driver for Raspberrypi which is already available in Linux kernel as staging driver.I m using Yocto to produce custom kernel
    But How to make my Raspberrypi kernel recognize the staging driver and function it operational ?
    Please help me to run the staging driver on Yocto kernel

  6. Well, that’s a bit off-topic for this post, but generally, after you’ve built your image with kernel module included, you just need to run “modprobe ” or “insmod ” and it should be loaded.

  7. This post is about adding an module whose source is already existing in the linux Kernel.

    Is there any article exist explaining how to add a psedo-driver/module say “a Hello world” module in Galileo’s yocto based linux image. Does it require to create new recipes and add somewhere in the Quark’s BSP source tree? Any clue on this would be highly appreciated.

  8. Well, I don’t know of any such articles. But generally, the process would not be much different, because it’s more of a Linux thing than Yocto here. You can take any Linux guide for writing drivers (just mind Galileo’s kernel version) and then add it like if it’s an in-tree one or an out-of-tree one (but in the second case you’d need to create a different recipe to pass all the necessaary information).

Leave a Reply

Your email address will not be published. Required fields are marked *