Skip to content

Build chrome os kernel and kernel modules

araisovich edited this page Jul 9, 2016 · 26 revisions

General info

This page will explain howto build your own chrome os kernel and kernel modules. We are especially interested in the kernel modules as we can't use a different kernel with crouton.
When you build your own kernel modules, you also are able to build the kernel. It could be of use for chrubuntu users.

If after building your kernel modules they are installed with an appended "-dirty", anything compiled against those installed headers will have a version inconsistent with the actual running kernel and may not load properly. This especially happens if one has retrieved an earlier commit from the kernel source git repository. See this article for information on how to retrieve an earlier version of the kernel source that matches your own, and how to remove checks during the build process that include the "-dirty" text.

Getting the kernel source

There are two git repos kernel and kernel-next where the kernel sources can be found, but you have to know which branch you're on. Branches can be identified by chromeos-version where version is your kernel version.
NOTE: Mostly you will need the kernel repo.
On the HP chromebook 14 I have kernel 3.8.11 so I need the chromeos-3.8 branch in the kernel repo.

To determine your kernel version you can use.

$ uname -r

First we need some tools installed in our chroot. I did this on a precise with xfce chroot, but it should also work on others.

Note: All the shell commands on this page need to be done in the shell of your chroot if not specified otherwise.

$ sudo apt-get install git-core make kernel-package

Cloning the kernel branch chromeos-3.8 to our home folder.

$ cd ~
$ git clone https://chromium.googlesource.com/chromiumos/third_party/kernel -b chromeos-3.8

Before we start building we need to setup our kernel config. More info can be found on the chromium dev pages

Note: You can obtain the current config of the chromeos by modprobe configs; zless /proc/config.gz, which should be more convenient and accurate.

First I had to turn off -Werror, because I got one small problem when building some wifi module. This could be a problem with the gcc compiler I used.
Just use your favorite text editor and edit "chromeos/config/base.config" in the kernel-next dir.

$ cd kernel
$ vi chromeos/config/base.config

Search for CONFIG_ERROR_ON_WARNING=y and make it CONFIG_ERROR_ON_WARNING=n

If you want to build extra modules that are in the kernel source, now is the time to enable them. For example say we want to build binfmt_misc.ko Search for "CONFIG_BINFMT_MISC" in chromeos/config/base.config. It should say

# CONFIG_BINFMT_MISC is not set

Change it to

CONFIG_BINFMT_MISC=m

Note: "m" stands for a separate module, if you choose "y" it will be build in the kernel. When build in the kernel, we can't use it. You will always need to choose "m" for a separate module so we can load and unload it.
Now prepare the kernel config.
Look at which flavor you need for your chromebook. We have x86_64 so we setup the config for chromeos-intel-pineview.
More info on which flavor to choose see the kernel config info site mentioned above.

$ ./chromeos/scripts/prepareconfig chromeos-intel-pineview

When you are cross compiling for arm, you will need some additional steps.
An example for setting a config for an arm chromebook device is.

$ ./chromeos/scripts/prepareconfig chromeos-exynos5

First you will need a cross compiler. On my ubuntu 14.04 64 bit notebook I used "gcc-arm-linux-gnueabi"

sudo apt-get install gcc-arm-linux-gnueabi

Now you only need to tell you will be cross compiling with arm-linux-gnueabi. You can do that by entering the following commands.

$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabi-

$ make oldconfig

If you enabled a module it can be that when running "make oldconfig" you will be asked to set additional config options needed for the module.
Most of the time it will be good to just leave them at the default. Which means just pressing enter at the input field.

Now you are all set to build the kernel and kernel modules. This is done by just typing make in the directory of your kernel source.
Note: Go get some coffee, this will take some time. You can speed up the build by using -j <job numbers>. On my i7 12Gb ram I use "-j 16" with no issues. However there can sometimes be some problems with parallel jobs, so if you get errors then try first without -j.

$ make

Note: If you encounter an error like

 error: unrecognized command line option ‘-fstack-protector-strong’

Then edit arch/<your architecture>/Makefile and search for -fstack-protector-strong then change it to -fstack-protector-all. I had this problem when building 3.4 kernel i386 and arm architecture. GCC below version 4.9 don't support -fstack-protector-strong.
When it is finished without errors, you can list the build modules (in our case binfmt_misc.ko) with.

$ find ./ -name *.ko|grep binfmt
./fs/binfmt_misc.ko

Unmount /lib/modules on enter chroot

Note: This step is only needed when you want to install the modules in /lib/modules. If not then you can skip this and go to Enable loading of kernel modules.
We need to unmount /lib/modules which is bind mounted in enter-chroot.
This can be done in rc.local.

Create the following /etc/rc.local or add this to your /etc/rc.local if you already have one.

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# unmount bindmounts /lib/modules from enter-chroot
for m in `cat /proc/mounts | /usr/bin/cut -d ' ' -f2 | grep /lib/modules| grep -v "^/$" `; do
        umount "$m"
done
echo 0

Also be sure to change the execution bit

$ sudo chmod +x /etc/rc.local

You can now logout and login again in your chroot to see if the script rc.local works.
If all is well, everything in /lib/modules is unmounted.
You can check this with the following.

$ cat /proc/mounts | grep /lib/modules

Installing build modules in /lib/modules/<kernel version>

$ sudo make modules_install
$ sudo depmod -a

This will install all modules in INSTALL_MOD_PATH which is by default / .
When you want to install it in a different path, to copy it to another chroot then change the INSTALL_MOD_PATH variable as follows.
As an example we use "tmp" directory in our kernel source directory.

$ export INSTALL_MOD_PATH="./tmp"
$ make modules_install

Enable loading of kernel modules.

To be able to load modules we need to disable module_locking, you can follow the procedure described in Enable kernel VT_x for Virtualbox that covers this as well. I also created a script change-kernel-flags to do this that can be found on divx118/crouton-packages.

Now load your module for example binfmt_misc.ko in the source tree.

$ sudo insmod ./fs/binfmt_misc.ko
Clone this wiki locally