Chromebooks and ChromeOS are giving an excellent browsing experience. The system is fast and with an ARM Chromebook, the autonomy is incredible.

The main issue with ChromeOS is the lack of good applications. All the google services are perfectly integrated but apart from this, the overall application library is poor. This fact has been partially addressed by the newest versions of ChromeOS with support of Android applications. Sadly, my old Chromebook is slowly reaching end of life (July 2018 according to google: and it never got support for Android applications.

As the HW still works perfectly, I decided to try installing my favorite OS: Debian! The main debian page looks old and did not provide too much information:

The best source of information is from the guys of Kali Linux. They provide ARM images for a lot of different systems.

The scripts used to generate these images are available on Github They provide an excellent basis to prepare an debian stretch image.

Developer Mode

The first to take control of the Chromebook is to switch to developer mode. This disable the kernel signature verification and let U run any firmware on the machine with the drawback of having at each startup an annoying warning screen…

  • First, turn off the machine
  • Press ESC + Refesh(F5) and Power-on @ the same time.
  • On the recovery screen appears, press CTRL-D
  • Confirm the switch by pressing enter and wait a (long) while.

Once developer mode is enabled, it’s possible to enable USB boot:

  • Boot the machine (pressing CTRL-D right after power-on).
  • Once chrome is ready, press CTRL-F2
  • Log as chronos with no password.
  • su - # Should give you root access.
  • Enable usb boot with: crossystem dev_boot_usb=1 dev_boot_signed_only=0

For more, look here: * Chrome documentation: * ArchArm linux:


All the steps described below require root priviledges. The simplest solution to get root is (depending on you linux distro):

su - # Asks for root password
sudo -s # Asks for current user password. Better if you have configured sudo

Deboostrap is a tool to install Debian in a folder. The operation is done in 2 stages: 1. Fetching all .deb files and unpacking them 2. Running all configuration scripts.

The 2nd stage require to be able to execute code and will not work if we try to install Debian armhf on a amd64 machine.

Fortunately, QEmu provides a user mode emulation which can launch processes from one CPU on another CPU! “Deboostraping” for a foreign architecture becomes easy by installing the package qemu-user-static:

apt-get install qemu-user-static
mkdir exynos
qemu-debootstrap --arch=armhf stretch exynos/root

This will fetch all debian packages required to get a base system for armhf architecture!


On such an old machine, XFCE makes an excellent lightweight desktop environment. To install it from the host system, the simplest is to prepare a bash script with the required steps and execute in it in a chroot, again relying on QEmu to execute the configuration.

# Update Apt sources
cat << EOF > exynos/root/etc/apt/sources.list
deb stretch main non-free contrib
deb-src stretch main non-free contrib
deb stretch/updates main contrib non-free

# Change hostname
echo "chromebook" > exynos/root/etc/hostname

# Add it to the hosts
cat << EOF > exynos/root/etc/hosts       chromebook    localhost
::1             localhost ip6-localhost ip6-loopback
fe00::0         ip6-localnet
ff00::0         ip6-mcastprefix
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

# Add loopback interface
cat << EOF > exynos/root/etc/network/interfaces
auto lo
iface lo inet loopback

# And configure default DNS (google...)
cat << EOF > exynos/root/etc/resolv.conf

packages="abootimg cgpt fake-hwclock ntpdate u-boot-tools vboot-utils vboot-kernel-utils \
        alsa-utils initramfs-tools laptop-mode-tools parted sudo usbutils \
        wpasupplicant firmware-linux firmware-linux-nonfree firmware-libertas firmware-atheros firmware-samsung \
        locales-all ca-certificates initramfs-tools u-boot-tools locales console-common less \
        dbus light-locker xfce4 xfce4-goodies xfce4-power-manager xfce4-terminal \
        network-manager-gnome xserver-xorg-video-fbdev xserver-xorg-input-synaptics \
        xserver-xorg-input-all xserver-xorg-input-libinput"

if [ ! -e exynos/root/root/third-stage ]; then
        cat << EOF > exynos/root/root/third-stage
apt-get update
echo "root:toor" | chpasswd
export DEBIAN_FRONTEND=noninteractive
apt-get -y install $packages
apt-get -y dist-upgrade
apt-get -y autoremove
apt-get clean
rm -f /0
rm -f /hs_err*
rm -rf /root/.bash_history
rm -f /usr/bin/qemu*
        mount -t proc proc exynos/root/proc
        mount -o bind /dev/ exynos/root/dev/
        mount -o bind /dev/pts exynos/root/dev/pts
        chmod +x exynos/root/root/third-stage
        LANG=C chroot exynos/root /root/third-stage
        umount exynos/root/dev/pts
        umount exynos/root/dev/
        umount exynos/root/proc


Some minor tweaking is required to get a correct usage experience:

mkdir -p exynos/root/etc/X11/xorg.conf.d/
cat << EOF > exynos/root/etc/X11/xorg.conf.d/10-synaptics-chromebook.conf
Section "InputClass"
        Identifier          "touchpad"
        MatchIsTouchpad             "on"
        Driver                      "synaptics"
        Option                      "TapButton1"    "1"
        Option                      "TapButton2"    "3"
        Option                      "TapButton3"    "2"
        Option                      "FingerLow"     "15"
        Option                      "FingerHigh"    "20"
        Option                      "FingerPress"   "256"

# Mali GPU rules aka mali-rules package in ChromeOS
cat << EOF > exynos/root/etc/udev/rules.d/50-mali.rules
KERNEL=="mali0", MODE="0660", GROUP="video"

# Video rules aka media-rules package in ChromeOS
cat << EOF > exynos/root/etc/udev/rules.d/50-media.rules
ATTR{name}=="s5p-mfc-dec", SYMLINK+="video-dec"
ATTR{name}=="s5p-mfc-enc", SYMLINK+="video-enc"
ATTR{name}=="s5p-jpeg-dec", SYMLINK+="jpeg-dec"
ATTR{name}=="exynos-gsc.0*", SYMLINK+="image-proc0"
ATTR{name}=="exynos-gsc.1*", SYMLINK+="image-proc1"
ATTR{name}=="exynos-gsc.2*", SYMLINK+="image-proc2"
ATTR{name}=="exynos-gsc.3*", SYMLINK+="image-proc3"
ATTR{name}=="rk3288-vpu-dec", SYMLINK+="video-dec"
ATTR{name}=="rk3288-vpu-enc", SYMLINK+="video-enc"
ATTR{name}=="go2001-dec", SYMLINK+="video-dec"
ATTR{name}=="go2001-enc", SYMLINK+="video-enc"
ATTR{name}=="mt81xx-vcodec-dec", SYMLINK+="video-dec"
ATTR{name}=="mt81xx-vcodec-enc", SYMLINK+="video-enc"
ATTR{name}=="mt81xx-image-proc", SYMLINK+="image-proc0"

# By default, it goes to powersave that reduces cpu freq to 200 Hz!
sed -i 's/BATT_CPU_GOVERNOR=ondemand/BATT_CPU_GOVERNOR=conservative/' exynos/root/etc/laptop-mode/conf.d/cpufreq.conf
sed -i 's/LM_AC_CPU_GOVERNOR=ondemand/LM_AC_CPU_GOVERNOR=performance/' exynos/root/etc/laptop-mode/conf.d/cpufreq.conf
sed -i 's/NOLM_AC_CPU_GOVERNOR=ondemand/NOLM_AC_CPU_GOVERNOR=performance/' exynos/root/etc/laptop-mode/conf.d/cpufreq.conf

At that point, we have a complete Debian distribution ready with XFCE4 pre-installed. What we are missing is … a Linux kernel!


To compile the kernel, we need a cross compiler. The simplest to get the one of Linaro:

wget -P exynos/..
tar xvjf exynos/../gcc-linaro-arm-linux-gnueabihf-4.7-2012.12-20121214_linux.tar.bz2 -C exynos

Google still provides updates to the kernel-3.8. The hardest is to get a good kernel config. On that particular point, the basis from Kali Linux was a great help. You can download mine here!

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
git clone --depth 1 -b release-${kernel_release} exynos/kernel
cd exynos/kernel
cp ../../${kernel_release} .config
make olddefconfig
make -j $(grep -c processor /proc/cpuinfo)
make dtbs
make modules_install INSTALL_MOD_PATH=`pwd`/../root

Boot image

cd arch/arm/boot
cat << __EOF__ > kernel-exynos.its

/ {
    description = "Chrome OS kernel image with one or more FDT blobs";
    images {
            description = "kernel";
            data = /incbin/("zImage");
            type = "kernel_noload";
            arch = "arm";
            os = "linux";
            compression = "none";
            load = <0>;
            entry = <0>;
            description = "exynos5250-snow-rev4.dtb";
            data = /incbin/("dts/exynos5250-snow-rev4.dtb");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
                algo = "sha1";
            description = "exynos5250-snow-rev5.dtb";
            data = /incbin/("dts/exynos5250-snow-rev5.dtb");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
                algo = "sha1";
    configurations {
        default = "conf@1";
            kernel = "kernel@1";
            fdt = "fdt@1";
            kernel = "kernel@1";
            fdt = "fdt@2";
mkimage -D "-I dts -O dtb -p 2048" -f kernel-exynos.its exynos-kernel
dd if=/dev/zero of=bootloader.bin bs=512 count=1
echo 'noinitrd console=tty1 root=PARTUUID=%U/PARTNROFF=2 rootwait rw lsm.module_locking=0 net.ifnames=0 rootfstype=ext4' > cmdline
vbutil_kernel --arch arm --pack kernel_usb.bin --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --version 1 --config cmdline --bootloader bootloader.bin --vmlinuz exynos-kernel
echo 'noinitrd console=tty1 root=/dev/mmcblk0p3 rootwait rw lsm.module_locking=0 net.ifnames=0 rootfstype=ext4' > cmdline
vbutil_kernel --arch arm --pack kernel_emmc_ext4.bin --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --version 1 --config cmdline --bootloader bootloader.bin --vmlinuz exynos-kernel
echo 'noinitrd console=tty1 root=/dev/mmcblk0p3 rootwait rw lsm.module_locking=0 net.ifnames=0 rootfstype=btrfs' > cmdline
vbutil_kernel --arch arm --pack kernel_emmc_btrfs.bin --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --version 1 --config cmdline --bootloader bootloader.bin --vmlinuz exynos-kernel
cd ../../../../../

Root archive

To create a “tar” archive of all the required files (but the kernel):

cd exynos/root
tar pczf ../rootfs.tgz *
cd ../..

Preparing the USB stick

Plug the USB key you want to use to boot the chromebook in debian and find it’s device name:

dmesg | tail
[ 6311.549555] scsi host11: usb-storage 4-3:1.0
[ 6312.582899] scsi 11:0:0:0: Direct-Access     Sony     Storage Media    1.00 PQ: 0 ANSI: 2
[ 6312.584143] sd 11:0:0:0: Attached scsi generic sg7 type 0
[ 6312.585623] sd 11:0:0:0: [sdg] 7831552 512-byte logical blocks: (4.01 GB/3.73 GiB)
[ 6312.586395] sd 11:0:0:0: [sdg] Write Protect is off
[ 6312.586403] sd 11:0:0:0: [sdg] Mode Sense: 23 00 00 00
[ 6312.587143] sd 11:0:0:0: [sdg] No Caching mode page found
[ 6312.587155] sd 11:0:0:0: [sdg] Assuming drive cache: write through
[ 6313.621281]  sdg: sdg1
[ 6313.624874] sd 11:0:0:0: [sdg] Attached SCSI removable disk


The content will be entirely erased!

Umount the partition:

umount /dev/sdg1

Create a new partition table compatible with Chrome bootloader:

parted /dev/sdg --script -- mklabel gpt
cgpt create -z /dev/sdg
cgpt create /dev/sdg
cgpt add -i 1 -t kernel -b 8192 -s 32768 -l KERN-A -S 1 -T 5 -P 10 /dev/sdg
cgpt add -i 2 -t kernel -b 40960 -s 32768 -l KERN-B -S 1 -T 5 -P 5 /dev/sdg
cgpt add -i 3 -t data -b 73728 -s `expr $(cgpt show /dev/sdg | grep 'Sec GPT table' | awk '{ print \$1 }')  - 73728` -l Root /dev/sdg
blockdev --rereadpt /dev/sdg
dd if=/dev/zero of=/dev/sdg3 bs=1M count=1
mkfs.ext4 -O ^flex_bg -O ^metadata_csum -L rootfs /dev/sdg3
cgpt show /dev/sdg
   start        size    part  contents
       0           1          PMBR
       1           1          Pri GPT header
       2          32          Pri GPT table
    8192       32768       1  Label: "KERN-A"
                              Type: ChromeOS kernel
                              UUID: 2E5495E4-4512-934B-B8C7-CE3DE7440D06
                              Attr: priority=10 tries=5 successful=1
   40960       32768       2  Label: "KERN-B"
                              Type: ChromeOS kernel
                              UUID: F3D45573-BE10-0F45-A1B2-665F4F05CCD8
                              Attr: priority=5 tries=5 successful=1
   73728     7757791       3  Label: "Root"
                              Type: Linux data
                              UUID: 5A3996B9-BF48-1E4F-BA9B-FBA8F1307821
 7831519          32          Sec GPT table
 7831551           1          Sec GPT header

Unplug / replug the USB key to mount it:

dmesg | tail
[ 6751.401218] scsi 11:0:0:0: Direct-Access     Sony     Storage Media    1.00 PQ: 0 ANSI: 2
[ 6751.402454] sd 11:0:0:0: Attached scsi generic sg7 type 0
[ 6751.403819] sd 11:0:0:0: [sdg] 7831552 512-byte logical blocks: (4.01 GB/3.73 GiB)
[ 6751.404590] sd 11:0:0:0: [sdg] Write Protect is off
[ 6751.404598] sd 11:0:0:0: [sdg] Mode Sense: 23 00 00 00
[ 6751.405462] sd 11:0:0:0: [sdg] No Caching mode page found
[ 6751.405475] sd 11:0:0:0: [sdg] Assuming drive cache: write through
[ 6752.450278]  sdg: sdg1 sdg2 sdg3
[ 6752.454119] sd 11:0:0:0: [sdg] Attached SCSI removable disk
[ 6752.920699] EXT4-fs (sdg3): mounted filesystem with ordered data mode. Opts: (null)

Copy the kernel of the 2 first partitions and unpack the rootfs

dd if=./exynos/kernel/arch/arm/boot/kernel_usb.bin of=/dev/sdg1
dd if=./exynos/kernel/arch/arm/boot/kernel_usb.bin of=/dev/sdg2
cd /media/phoenix/rootfs
tar xzf $curdir/exynos/rootfs.tgz ; sync
cd $curdir

Eject the key, plug it in the black usb port (ie USB2.0). Power-on the machine and press CTRL-U. You should boot in your fresh debian installation!

Login: root Password toor

Don’t forget to change it!