Dual Boot ChromeOS & Linux on a Chromebook

You will need:

  • A Chromebook, obviously (Haswell or Broadwell, although it may also work with older Chromebooks, doesn’t seem to work with Baytrail)
  • 2 or more USB sticks
  • An appropriate distro ISO

Please note – As a result of booting ChromeOS from SeaBIOS, the HWID is not available, therefore ChromeOS will not update. To update, you will need to flash back to the stock BOOT_STUB or use CTRL + D in the case of RW_LEGACY to boot ChromeOS as normal, then instigate an update yourself, and flash the modified BOOT_STUB again if you need to.

If you’ve already flashed your Chromebook to install Linux previously, you will need to flash back to stock, if running a modified BOOT_STUB/Full ROM. You’ll then need to run ChromeOS recovery. If you’ve previously modified your RW_LEGACY slot, it’s worth bearing in mind that ChromeOS Recovery will flash the stock RW_LEGACY, regardless of what state of functionality it leaves you in. In this case you will need to flash the modified RW_LEGACY slot again.

This procedure was tested on an Acer Chromebook 15, and an HP Chromebook 14.

From ChromeOS Crosh shell, we firstly need to resize the stateful partition to make some space for Linux, like so:

sudo cgpt add -i 1 -s 4194304 /dev/sda

Here, we have told cgpt to resize partition 1 to 2 GB in size. This is how you workout what the argument for -s should be:

Size you want in GB * 1024 (gives MB) * 1024 (gives KB) * 1024 (gives bytes) / 512 (to give number of 512 byte sectors). Remember you probably want 8 GB minimum for a Linux install, so on a 16GB eMMC/SSD as comes standard in many Chromebooks, this should be about right.

Next we need to disable rootfs verification, so we can plonk a copy of the ChromeOS kernel into the root of the third partition, for Grub2 to pick up and use, later on:

sudo /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions 2

Next, we need to get our copy of the ChromeOS kernel and put it on a USB stick. Warning – although many distro’s contain a “vboot_utils” package, vbutil_kernel doesn’t have the same functionality as in ChromeOS, hence why we need to do it now:

sudo vbutil_kernel --get-vmlinuz /dev/sda2 --vmlinuz-out /media/removable/UNTITLED/chromeos-vmlinuz

Where “UNTITLED” is the label of your USB stick.

We also want a copy of the current boot record and partition layout (this is important so you can boot the “normal” way on occasion, and actually update ChromeOS, otherwise ChromeOS Recovery will like to wipe your disk):

sudo dd bs=1k count=32 if=/dev/sda of=/media/removable/UNTITLED/chromeos-gpt.bak

Now would probably be a good time to reboot, and check the damned thing still works. :)

If appropriate, now is the time to flash the modified BOOT_STUB.  Also, have your Linux Live USB plugged in, then reboot.

Install your distro as normal, but leave the ChromeOS partitions intact. Fedora will insist you create at least 2 partitions – 1 for “biosboot” (an area for Grub to store itself) and another for the system – /dev/sda13 and /dev/sda14 respectively.

Reboot again, and take another copy of the disks partition table as above, but replacing the name appropriately. Then you should copy your vmlinuz file to the root of /dev/sda3.

Now onto configuring Grub. In /etc/grub.d/40_custom add:

menuentry "Chrome OS" {
 insmod part_gpt
 insmod ext2
 set root=(hd0,gpt3)
 linux /vmlinuz root=/dev/sda3 rw noresume noswap i915.modeset=1 loglevel=1 quiet noinitrd tpm_tis.force=1
 }

There’re a couple of important things here. Firstly we want to make sure Grub is loading GPT support (as we’re using ChromeOS’ GPT layout, hence part_gpt). We have to also make sure we refer to the partition as “gpt” as opposed to “msdos”, as would be “normal”, and we’re adding a kernel cmdline option to effectively bypass the TPM. The latter is needed otherwise ChromeOS takes 10 minutes trying to start, using the TPM for user directory encryption. All good fun.

Run update-grub/grub2-mkconfig > /boot/grub2/grub.cfg and reboot again to test the ChromeOS option.

That should be about all that’s needed. If you need to update ChromeOS you will have to flash back the stock BOOT_STUB (if you’re using it), and dd back the chromeos GPT layout, then start ChromeOS normally. Obviously, you need to be careful you do both of those at the same time, otherwise you could leave yourself with a semi-unbootable system which will require wiping with ChromeOS recovery. Conversely, when you have updated, you will need to flash back the modified BOOT_STUB and dd back the distro GPT layout to get back into the dual boot setup.

One more thing, in my attempts to get this working on Baytrial I ascertained that the following commands are needed to bypass the default partition maximum of 8 for MMC devices in Linux:

umount /dev/mmcblk0p[1,3,5]
sudo modprobe -r mmc_blocksudo modprobe mmc_block mmcblk.perdev_minors=32

If anyone wants to pick that up and run with it in terms of getting ChromeOS to actually boot using this dual-boot setup, be my guest.