Back to post index

Installing stock Debian on the Samsung ARM Chromebook
Tags: [debian] [chromebook] [arm]
Published: 07 Jun 2014 09:34

Post Summary

This post explains how to install Debian wheezy onto an SD card for use with the Samsung ARM Chromebook (model number XE303C12), and how to compile Linux 3.15-rc7 so that the Chromebook boots with a (mostly) stock Linux kernel.

Table of contents:


An ARM Chromebook running stock Linux would be a great travel workstation:

Unfortunately, it is not straight forward to boot stock Debian with a stock Linux kernel on this device. It does not have a standard BIOS or bootloader.

This post explains how I set up my Chromebook. At the end, you should have a (mostly) stock Linux kernel booting a stock Debian distribution:

However, there are still some things that do not work (more on that later).

Process summary

See for each of the linked scripts here.


Be careful, these scripts are dangerous to run if you don’t know what you’re doing. Be sure to check that the device targets and mount points are sane for your setup.

Preparing the Chromebook

First, I followed the instructions at the ARMChromebook page.


The Chromebook will boot from a SD card.

Setting up the SD card


The following script sets up the SD card partitions:


# On a Linux workstation


set -x

# Zero out current partition table
dd if=/dev/zero of=${DEV} bs=512 count=1

# Partitioning the device:
parted --script ${DEV} mklabel gpt

cgpt create ${DEV}

cgpt boot -p ${DEV}

# from
# Partition 1: Kernel partition, regular Chrome OS kernel for whatever need you might have (i.e. same as previous instructions)
# Partition 2: Another kernel partition with nv-u-boot on it at higher priority
# Partition 3: Ext2 filesystem for /boot (important, should be ext2)
# Partition 4: rootfs for Linux, ext4 or whatever you prefer
# plus:
# Partition 5: home partition, encrypted

# cgpt expects 512-byte blocks:
let "max=`blockdev --getsz ${DEV}`"

let "offs=512"
let "size=1280"
cgpt add -b ${offs} -s ${size} -t kernel -P 2 -S 1 -l CHROMEOS ${DEV}

let "offs = offs + size"
let "size=128000"
cgpt add -b ${offs} -s ${size} -t kernel -P 3 -S 0 -T 10 -l NVUBOOT ${DEV}

let "offs = offs + size"
let "size=1280000"
# size = 625 MiB
# >>> 1280000.0 * 512 / 1024 / 1024
# 625.0
cgpt add -b ${offs} -s ${size} -t rootfs -P 1 -S 1 -l BOOT ${DEV}

let "offs = offs + size"
let "size = (max - offs) / 4"
cgpt add -b ${offs} -s ${size} -t rootfs -P 1 -S 1 -l ROOT ${DEV}

let "offs = offs + size"
let "size = max - offs - 1024"
cgpt add -b ${offs} -s ${size} -t rootfs -P 1 -S 1 -l HOME ${DEV}

cgpt show ${DEV}

exit 0

Be sure to edit this script by changing the following lines:


As root, plug in your SD card and run

A tool like gparted will display the partition layout of the SD card visually.

The reason for this partition layout is that the nv-uboot (non-verifying UBoot) that Google supplies expects this partition layout, according to

Installing the bootloader

Download nv_uboot-snow-simplefb.kpart from :

wget -O - | bunzip2 > nv_uboot-snow-simplefb.kpart

The bootloader should be written to partition 2. From your Linux workstation, run as root:


# On a Linux workstation


set -x

dd if=nv_uboot-snow-simplefb.kpart of=${DEV}2

exit 0

Remember again to modify the DEV variable!

Creating other filesystems

Three of the other partitions hold target filesystems:

The reason that /home is separated is that I encrypted this partition. I did this because being a travel workstation, the probability of loss or theft is higher than a normal workstation. I want to have the peace of mind that comes with not worrying what a theft could mean for my data.

Running as root creates the filesystems:


# On a Linux workstation


set -x

blockdev --rereadpt ${DEV}

# BOOT: /boot
mkfs.ext2 ${DEV}3

# ROOT: /, where debian root goes
mkfs.ext4 ${DEV}4

# HOME: luks encrypt
cryptsetup luksFormat ${DEV}5

exit 0

Remember again to modify the DEV variable!

If the following is seen:

+ mkfs.ext2 /dev/sdb3
mke2fs 1.42.10 (18-May-2014)
mkfs.ext2: Device size reported to be zero.  Invalid partition specified, or
        partition table wasn't reread after running fdisk, due to
        a modified partition being busy and in use.  You may need to reboot
        to re-read your partition table.

then remove and insert your SD card and try again. If that doesn’t work, you might need to write zeroes to the whole SD card and try again. This happened to me when I used my USB SD card reader and writing zeroes to the whole SD card worked for me.

debootstrap Debian wheezy

This is a two stage Debian bootstrap:

The commands are simple. First, as root, run to start the first debootstrap stage targeting wheezy:


# On a Linux workstation


set -x

# mount ROOT (/), and debootstrap into it
mount ${DEV}4 ${MNT}

debootstrap --arch=armhf --foreign wheezy ${MNT}

umount ${MNT}

exit 0

Next, on the Chromebook, boot into ChromeOS and switch over to the root shell with Ctrl-Alt-F2 (right arrow on esc row). This will only be possible if the Chromebook was switched into developer mode. Connect the Chromebook to the internet, change into /usr/local/, and then save and run


# On the Chromebook


# Chroot into the SD card, and perform the second debootstrap stage

umount ${DEV}p[1-5]

mount ${DEV}p4 ${MNT}
[[ ${?} -eq 0 ]] || exit 1;

# Bind the following special filesystems for use in the chroot
mount --bind /dev/ ${MNT}/dev/
[[ ${?} -eq 0 ]] || exit 1;
mount --bind /proc/ ${MNT}/proc/
[[ ${?} -eq 0 ]] || exit 1;
mount --bind /sys/ ${MNT}/sys/
[[ ${?} -eq 0 ]] || exit 1;

chroot ${MNT} /debootstrap/debootstrap --second-stage
[[ ${?} -eq 0 ]] || exit 1;

# Setup /etc/fstab for the two unencrypted partitions

cat > ${MNT}/etc/fstab <<EOF
${DEV}p4 / ext4 errors=remount-ro 0 1
${DEV}p3 /boot/ ext2 errors=remount-ro 0 1

# Populate the /etc/apt/sources.list with target = wheezy

cat > ${MNT}/etc/apt/sources.list <<EOF
deb wheezy main non-free contrib
deb-src wheezy main non-free contrib

# Update the packages

chroot ${MNT} apt-get update
[[ ${?} -eq 0 ]] || exit 1;

chroot ${MNT} apt-get upgrade
[[ ${?} -eq 0 ]] || exit 1;

# Install useful packages
chroot ${MNT} apt-get install wpasupplicant iw upower cryptsetup

echo "yourhostname" > ${MNT}/etc/hostname

# Set the root password

# Copy over built-in wireless firmware
mkdir ${MNT}/lib/firmware/mrvl/
cp /lib/firmware/mrvl/* ${MNT}/lib/firmware/mrvl/

umount ${MNT}/dev/
umount ${MNT}/proc/
umount ${MNT}/sys/
umount ${MNT}

exit 0

I chose tal as a hostname.

The Debian distribution is now installed onto the SD card - test with

chroot ${MNT}

to get into the bash shell.

Compiling the Chromebook’s Linux kernel

Set up cross compilation toolchain

I used crosstool-ng with the following configuration:

Paths and misc options  --->
(${HOME}/dl) Local tarballs directory
Target options  --->
    Target Architecture (arm)  --->
(v7) Suffix to the arch-part
    Endianness: (Little endian)  --->
    Bitness: (32-bit)  --->
    Floating point: (hardware (FPU))  --->
Operating System  --->
    Target OS (linux)  --->
    Linux kernel version (3.12)  --->

Download and compile Linux 3.15-rc7

Get the Linux kernel source from The Linux Kernel Archives. Linux 3.15-rc7 is available at the time of this article’s writing.

$ gpg --verify linux-3.15-rc7.tar.sign
gpg: Signature made Sun 25 May 2014 07:08:30 PM EDT using RSA key ID 00411886
gpg: Good signature from "Linus Torvalds <>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: ABAF 11C6 5A29 70B1 30AB  E3C4 79BE 3E43 0041 1886

From within the linux-3.15-rc7 directory created from un-tarring linux-3.15-rc7.tar.xz, call


export PATH="${HOME}/x-tools/armv7-unknown-linux-gnueabi/bin/:${PATH}"

# from
# ARCH            ?= arm
# CROSS_COMPILE   ?= arm-unknown-linux-gnu-

export ARCH=arm
export CROSS_COMPILE=armv7-unknown-linux-gnueabi-


set -x
make ${makeopts} clean distclean mrproper
set +x

if [[ ${rc} -ne 0 ]];
    echo "make clean distclean returned ${rc}!";
    exit ${rc};

set -x
make ${makeopts} exynos_defconfig
set +x

if [[ ${rc} -ne 0 ]];
    echo "make exynos_defconfig returned ${rc}!";
    exit ${rc};

exit 0;

Patching the kernel for built-in wireless support

I needed to apply the following patches from for the built-in wireless networking to work:

Grab 06-built-in-wireless.patch and :

patch -p0 < 06-built-in-wireless.patch

Kernel configuration

This was the tricky part for me. Until the Chromebook worked, I had never booted successfully from a Linux kernel I compiled myself.

My process for figuring out which configuration options to choose involved every modification to the kernel configuration being saved into config_good, which was versioned with git. I used the iFixit teardown of the Chromebook as a reference for the components on the motherboard, and found those in the kernel configuration file.

This seemed strange - why wasn’t there a program that would look at my system and select the appropriate kernel configuration options? Turns out that there is:

`make localmodconfig`

Before making this blog post, I had a working Chromebook with Debian on it. So, I scp’ed the linux-3.15-rc7.tar.xz over to the Chromebook, and performed the localmodconfig to get a .config file for the Chromebook automatically! But it didn’t work.

Here are the menuconfig options I changed:

General setup  --->
    [*] Control Group support  --->

CPU Power Management  --->
    CPU Frequency scaling  --->
        [*] CPU Frequency scaling
              Default CPUFreq governor (ondemand)  --->
        <*>   'powersave' governor
    CPU Idle  --->
        [*] CPU idle PM support

[*] Networking support  --->
    -*-   Wireless  --->
        <*>   cfg80211 - wireless configuration API
        [*]     cfg80211 wireless extensions compatibility
        <*>   Generic IEEE 802.11 Networking Stack (mac80211)

Device Drivers  --->
    [*] Network device support  --->
        [*]   Wireless LAN  --->
            <*>   Marvell WiFi-Ex Driver
            <*>     Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8897
    Character devices  --->
        <*> EXYNOS HW random number generator support
    [*] Power supply class support  --->
        <*>   SBS Compliant gas gauge
        <*>   TPS65090 battery charger driver
        [*]   Board level reset or power off  --->
            [*]   GPIO power-off driver
        [*]   Restart power-off driver
    Graphics support  --->
        [*] Backlight & LCD device support  --->
            <M>     Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED
            <M>     Backlight Driver for ADP8870 using WLED
            <M>     Backlight Driver for LM3630A
            <M>     Backlight Driver for LM3639
            <M>     Backlight driver for TI LP855X
            <M>     Generic GPIO based Backlight Driver
            <M>     Sanyo LV5207LP Backlight
            <M>     Rohm BD6107 Backlight
    [*] Real Time Clock  --->
        <*>   Maxim MAX77686
    [*] Pulse-Width Modulation (PWM) Support  --->
        <*>   Samsung PWM support

-*- Cryptographic API  --->
    <*>   XTS support
    <*>   AES cipher algorithms (ARM-asm)

Using 07-chromebook-kernel-config.patch:

cp .config config_good
patch -p0 < 07-chromebook-kernel-config.patch
cp config_good .config

Then, run


export PATH="${HOME}/x-tools/armv7-unknown-linux-gnueabi/bin/:${PATH}"

# from
# ARCH            ?= arm
# CROSS_COMPILE   ?= arm-unknown-linux-gnu-

export ARCH=arm
export CROSS_COMPILE=armv7-unknown-linux-gnueabi-


set -x
make ${makeopts} uImage dtbs -j5
set +x

if [[ ${rc} -ne 0 ]];
    echo "make returned ${rc}!";
    exit ${rc};

# make modules

make -j5

mkdir dist/
make modules_install INSTALL_MOD_PATH=${PWD}/dist/

exit 0;

As root, install the new kernel uImage and dtb exynos5250-snow.dtb to your SD card with


# On a Linux workstation


set -x

# Mount / and /boot/, then copy over compiled kernel and modules

mount ${DEV}4 ${MNT}
mount ${DEV}3 ${MNT}/boot/

cp arch/arm/boot/uImage arch/arm/boot/dts/exynos5250-snow.dtb ${MNT}/boot/

rm -rf ${MNT}/lib/modules/*

rsync -avAX dist/ ${MNT}/

umount ${MNT}/boot/
umount ${MNT}

exit 0

If the cross-compilation toolchain is correct, then the Chromebook should boot into Linux 3.15-rc7 without trouble:

If not,

If all that doesn’t help, then I recommend either asking questions in #debian-arm on, or email me at jwm @ this domain and I will try to help.

A note about UBoot environment variables

If Linux will not boot, check the UBoot environment variables.

After pressing Ctrl-u, hold space to stop UBoot’s booting process. This drops you into a shell, where you can use commands like printenv and setenv to view and modify environment variables.

nv_uboot-snow-simplefb ships with different environment variables than the non-simplefb version also available from Google. Before using the simplefb version, I used the non-simplefb version. At some point, I must have modified the non-simplefb version’s environment variables and then executed saveenv, saving these to some internal flash.

I had problems until I installed nv_uboot-snow-simplefb and reset the saved environment to what ships with nv_uboot-snow-simplefb:

env default -f

Final steps

Encrypting the home partition

No regular user has been created yet. Before creating your day-to-day user id, set up the encrypted home partition.

As root:

cryptsetup luksOpen /dev/mmcblk1p5 sdenc
mkfs.ext4 /dev/mapper/sdenc
mount /dev/mapper/sdenc /home/

After this you can add a regular user with the adduser command.

To close the encrypted home partition:

umount /home/
cryptsetup luksClose sdenc

I wrapped the creation and closing of the home partition into two bash scripts.

extra packages

apt-get install openbox tint2 iceweasel
apt-get install xterm
apt-get install xcompmgr
apt-get install vim
apt-get install ntp
apt-get install build-essential

configuring a better touchpad

I modified 10-synaptics-chromebook.conf from the ChromeOS partition.


What works

What doesn’t work


Thanks to Aardvark and hrw on #debian-arm for answering my questions and helping me debug problems.