-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Build chrome os kernel and kernel modules
This page will explain how to 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 are also able to build the kernel, so it could be of use for chrubuntu users.
In latest versions of Chrome OS, Google uses Git version as part of the kernel name (what used to be a simple 3.18.0
version is now 3.18.0-00000-xxxxxxxx
). Since kernel modules are compiled against a specific kernel version, it leaves no choice but to recompile the modules against each version of the OS's kernel every OS update.
A wise choice would be to stay on the Stable channel, for much less frequent updates.
Moreover, while this process can be done inside your chroot on the chromebook itself (tested on a precise with xfce), it would be wise to do this on a capable Linux machine since all the tools coupled with the repo can weigh a couple of GB, which will chock up an average chromebook.
Let's start up by ensuring all the required tools are properly installed:
$ sudo apt-get install git-core make kernel-package bc nano
Now we have to find out our kernel version.
Fire up crosh using Ctrl+Alt+T
and type in:
$ uname -r
NOTE: This command alone must be typed inside your chromebook machine.
Note: There are two git repos where the kernel sources can be found: kernel and kernel-next, however mostly you will need the kernel repo.
Now we need to clone the Chrome OS repo to our machine. But before that, we need to understand on which branch we are.
Branches can be identified by chromeos-version where version is your kernel version, which we found on the our last command.
EXAMPLE: HP chromebook 14 has kernel 3.8.11 so you would need to use the chromeos-3.8 branch.
Cloning the kernel branch chromeos-3.8 to the current folder:
$ git clone https://chromium.googlesource.com/chromiumos/third_party/kernel -b chromeos-3.8
NOTE: This process should take quite some time. At least an hour on a typical internet connection. Also, make sure you have at least 10GB of free space on your hard-drive.
This step should be done in case you're building for a specific Git version (see note in introduction for more information). Otherwise, you can jump straight to Step 6.
Let's say our kernel version from Step 1 was 3.18.0-00000-xxxxxxxx
. In this case, you'd want to checkout to your specific version using:
$ git checkout 00000-xxxxxxxx
NOTE: You replace 00000-xxxxxxxx
with your own numbers.
Since we're not on the latest version anymore, a -dirty
flag would be added to our kernel version, which is a bad thing, since it has to match exactly the kernel version on our chromebook.
To get rid of this flag, we need to edit scripts/setlocalversion
:
$ nano scripts/setlocalversion
Inside this file, look for the following If statement (located inside scm_version()
function):
if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then
printf '%s' -dirty
fi
Mark those 3 lines a comment by putting a #
in the beginning of each line.
You can obtain the current configuration file of Chrome OS by:
$ modprobe configs; zless /proc/config.gz
$ cat /proc/config.gz | gunzip > ~/Downloads/base.config
NOTE: This step should be done from inside your chroot.
Now we ended up with a file called base.config
which contains all the current configuration of our kernel.
This file should replace the current file on path chromeos/config/base.config
.
If you want to build extra modules that are in the kernel source but not enabled by default, you do so by editing the flag for those modules. There are basically 3 flags you should be aware of:
-
n
which stands for "No". Means this module will not be built. -
y
which stands for "Yes". Means this module will be built into the kernel. -
m
which stands for "Module". Means this module will be separated from the kernel.
You will always want to choose "m" for a separate module so you can load and unload it.
Example: Let's say we want to build binfmt_misc.ko
:
$ nano chromeos/config/base.config
Search for CONFIG_BINFMT_MISC
. It should say:
# CONFIG_BINFMT_MISC is not set
Change it to:
CONFIG_BINFMT_MISC=m
Other modules you may want to consider enabling are md5.ko (CONFIG_CRYPTO_MD5)
, cifs.ko (CONFIG_CIFS)
and autofs.ko (CONFIG_AUTOFS4_FS)
.
During the build process you may face various errors. Some of them will throw you out of the process, forcing you to deal with them one way or another, some will simply warn you but won't stop the process.
A good way to ignore all those errors would be turning off the ERROR_ON_WARNING
flag in base.config
:
$ nano chromeos/config/base.config
Search for:
CONFIG_ERROR_ON_WARNING=y
Change it to:
CONFIG_ERROR_ON_WARNING=n
When you are cross compiling for arm, you will need some additional steps.
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-
Now we need to prepare the config file in accordance to our "flavor". More info on this can be found on the chromium dev pages.
If you wish to build for an x86_64 chromebook, you should use the chromeos-intel-pineview
flag. Otherwise, you should consult with the website mentioned above.
$ ./chromeos/scripts/prepareconfig chromeos-intel-pineview
An example for setting a config for an arm chromebook device:
$ ./chromeos/scripts/prepareconfig chromeos-exynos5
Now, let's prepare everything:
$ make oldconfig
Note: If you enabled modules on Step 7, you may 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. Make sure you're in the dictionary of your kernel source.
Here you can take the short way, and compile only the modules themselves (in most cases that's what you'd want to do):
Note: You must know the exact path of your module folder. In this case, we're building the CIFS module, which nests in a folder called fs
.
$ make prepare
$ make M=fs/cifs
In case you want to compile the whole kernel, you should simply do:
$ make
Go get some coffee, this will take some time. You can speed up the build by using -j \<job numbers\>
. On a i7 12Gb ram you may 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
.
- While running
make oldconfig
you get an error such as:drivers/net/Kconfig:6:warning: environment variable WIFIVERSION undefined
. If you're just building modules, you may go ahead and ignore this error, as it won't affect the outcome. - If you encounter an error like
error: unrecognized command line option ‘-fstack-protector-strong’
, then you should edit your make file:$ nano ./Makefile
Then you need to find and replace the string-fstack-protector-strong
with-fstack-protector-all
. It should look something similar to this:
ifdef CONFIG_CC_STACKPROTECTOR_STRONG
stackp-flag := -fstack-protector-all
ifeq ($(call cc-option, $(stackp-flag)),)
$(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
-fstack-protector-all not supported by compiler)
When it is finished without errors, you can list the build modules (in this case, binfmt_misc.ko) with:
$ find ./ -name *.ko | grep binfmt
./fs/binfmt_misc.ko
Google releases a new version of Chrome OS on Stable channel every 3 weeks or so. That means, in order to keep your modules working, you have to recompile them every new OS update. That's very frustrating, but that's how Google decided Chrome OS kernel to be (see introduction for more details).
In order to simply start over after an unsuccessful compile without changing to a different branch, you can simply run:
$ make clean
To reset your local source code to be up to date with Google's changes, you simply run:
$ git reset --hard origin/chromeos-3.18
Note: Mind your kernel version. (in the example above: 3.18) And then start again from Step 2 (skip Step 3, as we already have the repository cloned).
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
$ 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
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