Translation(s): none

DebianOn is an effort to document how to install, configure and use Debian on some specific hardware. Therefore potential buyers would know if that hardware is supported and owner would know how get the best out of that hardware.

The purpose is not to duplicate the Debian Official Documentation, but to document how to install Debian on some specific hardware.

Models covered
Asus C201 (2015-2016 ARM Chromebook)
Other models following Google Veyron Pinky platform (AKA, RK3288 based Chromebook/Chromebox) should work the same way (not tested). This submodel is named Veyron Speedy

Sub-models options :
- SoC: Rockchip RK3288
- CPU: Quad ARM Cortax-A17 at 1.8 GHz
- GPU: Mali T764
- Audio processor: Rockchip I2S
- Screen size: 11.6"
- Ram: 2 or 4 GB of ram

Overall Status

Core Components


Boot Standard Kernel:

[?] (can compile kernel from Chromium source)

Detect hard drives:


Extra Features

CPU Frequency Scaling




Sleep / Suspend




- OpenGLES


- Resize-and-Rotate(randr)


Hardware video decoding




Switch to External Screen



- Built-in (Touchpad)




Legend :
{OK} = OK ; {X} Unsupported(No Driver) ; /!\ = Error (Couldn't get it working); [?] Unknown, Not Test ; [-] Not-applicable
{i} = Configuration Required; X-( = Only works with a non-free driver and or firmware

Important Note

There are several methods of installating other operating systems on Chromebooks.

Crouton can install Debian as a chroot under Chrome OS (but that is not described here).

Debian can be installed on a USB stick/microSD card, or installed on the internal memory (mmcblk0).

Preparing for the installation


The laptop ships with coreboot as the bootloader.

Optionally, you may consider to replace coreboot with the Free libreboot. Consider that libreboot r20160907-20-gb204a20 seems to require kernels signed with version 2.2, and fail to boot with 2.0. This means the vboot-kernel-utils package in jessie (0~20121212-3) does not work, but the one in stretch (0~R52-8350.B-2) does. The vboot_kernel binary present in the factory ?ChromeOs also seems to work. In case you want to install the stretch version in jessie the only dependency is libssl1.0.2 which you'd have to install from stretch too.

Enabling Developer Mode

All of the installation techniques described require that the Chromebook be switched into Developer Mode. There are disadvantages to making this switch - see the link for more details, but it is currently a hard requirement.

Simply, developer mode can be enabled by first entering Recovery Mode (hold the ESC and Refresh keys then press the Power key). The system will reboot and show the Recovery Mode screen. Press Control-D or wait 30 seconds. The system will boot and ask you to confirm that you wish to make the change.

Switching to recovery mode will delete any content or data stored on your system.

Enabling Developer Mode proceeds and may take over 10 minutes to complete.

Enabling USB/SD card boot

All of the installation techniques described require that the Chromebook be able to boot from either a USB device or an SD card.

There are two methods, for this, using a text console shell (standard Linux shell), or using graphical user interface. In both case, the shell will be needed for installing the kernel on the SDcard so you probably want to read this.

Using console shell

* Note: You should be able to do this as guest, without the need to have or create a Google Account. In some case, you are prompted for a password at sudo time, this is a known bug, in this case, you simply need to reset your Chromebook system (Powerwash in ChromiumOS/ChromeOS terminology) again.

To enable this, first enable Developer Mode, then boot the system and start crosh. This can be done by pressing the Control, Alt and T keys simultaneously with in Chromium browser. A new window will open showing a terminal-style prompt. Here it is necessary to type shell, followed by sudo -s. You should now have a root shell prompt.

Enable boot from USB/microSD with crossystem dev_boot_usb=1. After this change the firmware boot screen will allow you to enter Control-D to boot from internal memory, or `Control-U' to boot from USB/microSD.

Using the Graphical User Interface

* Note: This feature is only accessible at the first installation or after a Powerwash.

On the first step screen of the first boot (or after a Powerwash), you have a windows where you can choose system language, keyboard and network. on the bottom-left part of this window there is a Enable debugging features link. Click on this link, then on the new window, after 2 or 3 seconds, new buttons will appear. Click then on Proceed, it will automatically activate USB/SD reader boot option and set the dev_boot_usb=1 flag.

Installing to an SD card using the ChromeOS kernel

This approach requires the enabling of both Developer Mode and USB/SD card boot. It uses the ChromeOS kernel and modules rather than the normal Debian kernel.

First, we prepare the SD card on a desktop machine. These instructions are for an 8G card, which affects on the second cgpt add call - you can adjust the size of the created partition as required.

Three partitions are created on the disk. In time, the intention is that these be used for:

  1. a kernel partition containing the standard (ChromeOS) kernel

  2. the root filesystem

* Note: If the card is mounted via USB reader or is a USB key, the device will be something like /dev/sdX. You can see the exact name of the device using dmesg at the time you connect it or by using df if the device is auto-mounted. In case of an USB device, the partition will not be ${DEV}p2, but instead ${DEV}2. Look again at this informations on the Chromebook itself if you use an external USB device instead of the internal card reader too.

# On a desktop machine (does not need to be ARM):
# Partitioning the device:
parted --script ${DEV} mklabel gpt
cgpt create ${DEV}
cgpt add -t kernel -l kernel -b 34 -s 32768 ${DEV}
cgpt add -t data -l / -b 32802 -s 15474621 ${DEV}
blockdev --rereadpt ${DEV}
# Create the root filesystem:
mkfs.ext2 ${DEV}p2
# Install the bootstrap packages in the root filesystem:
mkdir -p ${MNT}
mount ${DEV}p2 ${MNT}
debootstrap --arch=armhf --foreign jessie ${MNT}
# Unmount the filesystems:
umount ${MNT}

Alternatively, you can use a root image from and extract it into the root filesystem on the SD with zcat initrd.gz | cpio -i, then you can go through the regular Debian installer. That will require you to come up with another method than the chroot hack below to extract the ChromeOS kernel (I used Crouton for that).

Now move the SD card to the Chromebook which is already booted with ChromeOS:

# On the Chromebook:
# Unmount from wherever ChromeOS decided to mount the device,
# remount where we want:
umount ${DEV}p2
mount ${DEV}p2 ${MNT}
# Complete the bootstrap:
chroot ${MNT} /debootstrap/debootstrap --second-stage
# Set up fstab:
cat > ${MNT}/etc/fstab <<EOF
${DEV}p2 / ext4 errors=remount-ro 0 1
# Set up the apt sources and update:
cat > ${MNT}/etc/apt/sources.list <<EOF
deb jessie main non-free contrib
deb-src jessie main non-free contrib
# Copy the resolv.conf file in a chroot env, so files can be fetched
cp /etc/resolv.conf ${MNT}/etc/resolv.conf
# Update the package list:
chroot ${MNT} apt-get update
# Install useful packages:
chroot ${MNT} apt-get install -y cgpt vboot-utils \
chroot ${MNT} apt-get install -y wicd-daemon wicd-cli \
   wicd-curses console-setup
# Set the root password to blank:
chroot ${MNT} passwd -d root
# Set the hostname:
echo "wowbagger" > ${MNT}/etc/hostname
# Guess which kernel partition is the latest.  Run cgpt show and see
# which one (KERN-A or KERN-B) has the highest priority.
cgpt show /dev/mmcblk0
# Copy the ChromeOS kernel to the root filesystem,
# In this example we'll assume it was KERN-B:
dd if=/dev/mmcblk0p4 of=${MNT}/boot/chromeos.kernel.signed
cp ${MNT}/boot/chromeos.kernel.signed ${MNT}/boot/vmlinuz
# Declare the kernel flags:
cat > ${MNT}/boot/kernel.flags <<EOF
console=tty1 printk.time=1 nosplash rootwait root=${DEV}p2 ro rootfstype=ext4 lsm.module_locking=0
# Sign the kernel:
cat > ${MNT}/boot/ <<EOF
vbutil_kernel --repack /boot/vmlinuz.signed --keyblock \
  /usr/share/vboot/devkeys/kernel.keyblock --version 1 \
  --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk \
  --config /boot/kernel.flags --oldblob /boot/chromeos.kernel.signed \
  --arch arm
chroot ${MNT} sh /boot/
# Write the signed kernel to the kernel partition:
dd if=${MNT}/boot/vmlinuz.signed of=${DEV}p1
# Mark the newly written kernel partition as good and set the
# priority:
cgpt add -i 1 -S 1 -T 5 -P 12 ${DEV}
# Copy the ChromeOS kernel modules into the root filesystem:
mkdir -p ${MNT}/lib/modules
cp -r /lib/modules/* ${MNT}/lib/modules
# Copy the non-free firmware for the wifi device:
mkdir -p ${MNT}/lib/firmware/
cp -r /lib/firmware/* ${MNT}/lib/firmware
# Umount the filesystems:
umount ${MNT}

You should now be able to reboot your system and press Control-U at the boot screen to boot from the SD card. There is no root password - you should set one.

If you are running a newer ChromeOS, CONFIG_VT may be disabled in the kernel. this prevents the creation of consoles and the starting of Xorg from current stable. You need to install a tool that uses the framebuffer directly to interact with your new operating system. A patch is available and tested, but has yet to make it to the point of being submittable to the Xorg development team. See:

Installing to internal memory from SD card

Once you have a working Debian installation on SD card, you can copy it to the internal memory. You should probably cgpt show /dev/mmcblk0 to make sure these directions make sense for your actual partition table.

# shrink ROOT-A and ROOT-B partitions
cgpt add -i 3 -s 32 /dev/mmcblk0
cgpt add -i 5 -s 32 /dev/mmcblk0
# expand STATE partition
cgpt add -i 1 -b 282688 -s 30470080 /dev/mmcblk0
mkfs -t ext4 /dev/mmcblk0p1
mount -t ext4 /dev/mmcblk0p1 /mnt
cp -ax / /mnt
# reconfigure kernel
cat > /mnt/boot/kernel.flags <<EOF
console=tty1 printk.time=1 nosplash rootwait root=/dev/mmcblk0p1 rw rootfstype=ext4 lsm.module_locking=0
vbutil_kernel --repack /mnt/boot/vmlinuz.signed --keyblock \
  /usr/share/vboot/devkeys/kernel.keyblock --version 1 \
  --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk \
  --config /mnt/boot/kernel.flags --oldblob /boot/chromeos.kernel.signed \
  --arch arm
dd if=/mnt/boot/vmlinuz.signed of=/dev/mmcblk0p2
umount /mnt
# set mmcblk0p2 to the high priority and successful
cgpt add -i 2 -P 10 -S 1 /dev/mmcblk0
# set mmcblk0p4 to low priority so it is not used
# (I put test kernels here and set it to -P 15 -T 1 -S 0)
cgpt add -i 4 -P 0 -S 0 /dev/mmcblk0



The X11 xserver-xorg-video-fbdev driver works.


Unknown if OpenGL ES will work, though it will probably require armsoc server and several files from Chrome OS /usr/lib:


Do not play with ALSA mixer - you may fry your speakers!

UCM profiles from Chromium OS are on a way to be included in Debian. In meantime copy /usr/share/alsa/ucm/ directory contents from Chromium OS. I enabled these UCM files by adding /usr/bin/alsaucm -c ROCKCHIP-I2S set _verb HiFi to /etc/rc.local.

To have sound with pulseaudio, add to /etc/pulse/ the following line :

Note: with linux-libre-4.8.10 and jessie rootfs it seems to work without this line, and it doesn't work with the line (pulseaudio first loads the autodetected card and then fails to load sysdefault sync and aborts).


ChromeOS uses a driver called cmt which is not packaged in Debian, but can be salvaged. The xserver-xorg-input-synaptics and xserver-xorg-input-mtrack drivers work.

The default synaptics settings do not work very well. see for something more chromeOS like.

Power Management

Suspend to memory works. Installing acpid and laptop-mode-tools provides /etc/acpi/actions/ that is run when the lid closes.

Hibernation/suspend to disk not tested.


brcmfmac driver talks to the built-in BRCM4354 via SDIO.

If btsdio gets loaded, then it will not suspend properly. Add blacklist btsdio to modprobe configuration (i.e. create /etc/modprobe.d/blacklist-btsdio.conf).

ChromeOS Kernel

Building a kernel is easy because Google shares the tree they use as part of the ChromiumOS open source project.

git clone linux-chromium
cd linux-chromium
# sometimes firmware/kernel versions are interdependent, so use whatever
# release your ChromeOS was at before installing Linux:
git checkout release-R43-6946.B-chromeos-3.14
./chromeos/scripts/prepareconfig chromiumos-rockchip
# IMPORTANT: the brcmfmac driver is only up to date in the wireless-3.8 tree
export WIFIVERSION=-3.8
make oldconfig
# if you want to:
make menuconfig
make zImage modules dtbs
# kernel.its is used to attach the devicetree to the image
cat > kernel.its << EOF

/ {
    description = "Chrome OS kernel image with one or more FDT blobs";
    #address-cells = <1>;
    images {
            description = "kernel";
            data = /incbin/("arch/arm/boot/zImage");
            type = "kernel_noload";
            arch = "arm";
            os = "linux";
            compression = "none";
            load = <0>;
            entry = <0>;
            description = "rk3288-speedy.dtb";
            data = /incbin/("arch/arm/boot/dts/rk3288-speedy.dtb");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
                algo = "sha1";
    configurations {
        default = "conf@1";
            kernel = "kernel@1";
            fdt = "fdt@1";
echo "console=tty1 debug noinitrd root=/dev/mmcblk0p1 rw rootwait" > cmdline

rm -f kernel.itb kernel.signed
mkimage -f kernel.its kernel.itb
vbutil_kernel --pack kernel.signed \
      --keyblock /usr/share/vboot/devkeys/kernel.keyblock \
      --version 1 \
      --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk \
      --config cmdline --vmlinuz kernel.itb --arch arm
dd if=kernel.signed of=/dev/mmcblk0p4
# mark mmcblk0p4 for a single try at high priority:
cgpt add -i 4 -P 15 -S 0 -T 1 /dev/mmcblk0
# to permanently install the kernel:
dd if=kernel.signed of=/dev/mmcblk0p2

Mainline Linux Kernel

Support for most features, including LCD and HDMI video framebuffer, eMMC, microSD, battery, and USB is available in mainline linux v4.8-rc2, and the debian kernel packages as of 4.8~rc8-1~exp1 (currently in experimental). Suspend doesn't seem to work reliably yet.

In order for eMMC support to work reliably, it may need a patch similar to commit 984926781122f034d5bc9962815d135b6c4a8e1d adjusted for rk3288-veyron-speedy.dts:

diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts
index a0d033f..500fd18 100644
--- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts
@@ -124,6 +124,11 @@
+&emmc {
+       /delete-property/mmc-hs200-1_8v;
 &vcc_5v {
        gpio = <&gpio7 21 GPIO_ACTIVE_HIGH>;

Submitted upstream:

Got linux to boot with an initrd with the version of depthcharge currently used by libreboot by using the following FIT image configuration (the order appeared to matter quite a lot):


/ {
    description = "Linux kernel image with one or more FDT blobs";
    #address-cells = <1>;
    images {
            description = "vmlinuz";
            data = /incbin/("vmlinuz-4.8.0-rc4-armmp");
            type = "kernel_noload";
            arch = "arm";
            os = "linux";
            compression = "none";
                algo = "sha1";
            description = "dtb";
            data = /incbin/("dtb-4.8.0-rc4-armmp");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
                algo = "sha1";
            description = "initrd.img";
            data = /incbin/("initrd.img-4.8.0-rc4-armmp");
            type = "ramdisk";
            arch = "arm";
            os = "linux";
            compression = "none";
                algo = "sha1";
    configurations {
        default = "conf@1";
            kernel = "kernel@1";
            fdt = "fdt@1";
                ramdisk = "ramdisk@1";

And install much like above:

mkimage -f kernel-initrd.its kernel-initrd.itb

futility --debug vbutil_kernel \
    --arch arm \
    --version 1 \
    --keyblock /usr/share/vboot/devkeys/kernel.keyblock \
    --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk \
    --bootloader cmdline \
    --config cmdline \
    --vmlinuz kernel-initrd.itb \
    --pack vmlinuz.signed \

dd if=vmlinuz.signed of=/dev/DISK_OF_CHOICE

System Summary


lsusb -v | grep -E '\<(Bus|iProduct|bDeviceClass|bDeviceProtocol)' 2>/dev/null

Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  bDeviceClass            9 Hub
  bDeviceProtocol         1 Single TT
  iProduct                2 DWC OTG Controller
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  bDeviceClass            9 Hub
  bDeviceProtocol         1 Single TT
  iProduct                2 DWC OTG Controller
Bus 001 Device 003: ID 04f2:b53a Chicony Electronics Co., Ltd
  bDeviceClass          239 Miscellaneous Device
  bDeviceProtocol         1 Interface Association
  iProduct                1
      (Bus Powered)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  bDeviceClass            9 Hub
  bDeviceProtocol         0 Full speed (or root) hub
  iProduct                2 EHCI Host Controller


List of loaded modules

Module                  Size  Used by
nfsv3                  30059  1
tun                    27097  2
nfs                   164067  3 nfsv3
lockd                  74978  2 nfs,nfsv3
sunrpc                210721  8 nfs,lockd,nfsv3
brcmfmac              227850  0
brcmutil               13403  1 brcmfmac
cfg80211              375964  1 brcmfmac
uvcvideo               68397  0
videobuf2_vmalloc      12929  1 uvcvideo
iio_trig_sysfs         12679  0
joydev                 17227  0
cros_ec_accel          12998  0
kfifo_buf              12833  1 cros_ec_accel


Some configuration files and sample outputs.