DISCLAIMER: This could all quite plausibly brick your Chromebook, and I take no responsibility for any damage you might inflict on it or yourself. Follow along at your own risk.
Most Chromebooks can run some flavour of GNU/Linux using the Chrubuntu method, running off the kernel that comes with ChromeOS. I found, however, that the ChromeOS kernel didn’t play well with recent X.org versions, and would refuse to recover from suspend, and not deal very well at all with having an external screen attached to it.
I also wanted to replace ChromeOS entirely with Arch on my Chromebook, because only 16 gigabytes of eMMC isn’t very convenient for dual booting. To accomplish this, I needed an external installation medium.
First of all, you’ll need to get your Chromebook into developer mode if you haven’t already. This is model specific, although for most recent models holding the Escape and Reload keys while booting should do the trick. If not, ask Google.
You’ll need to be able to boot into a system that isn’t running off the internal eMMC drive in order to rewrite it. We’ll be making a USB drive with ChromeOS on it for this purpose.
Follow the instructions here to accomplish this. I recommend you also install some flavour of Chrubuntu on it, or you’ll have to somehow get a build environment sufficient to compile a Linux kernel onto your ChromeOS installation on your own. I recommend installing Arch, as it provides the vboot-utils
package that you’ll need for building the kernel image, but you should be able to compile this from source on any system.
Boot into your USB drive system by pressing Ctrl+U
at the firmware screen.
The ChromeOS firmware looks for disk partitions of type 7f00
(“ChromeOS kernel”), and generally picks the partition with the highest priority as the boot partition. This partition should contain a signed bootable kernel image, which you can make from a compiled kernel, a bootloader and the appropriate signing keys.
You’ll need to install the VBoot tools first. You can get the source from Google:
$ git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference
If you’re on Arch with AUR set up, you can just install the vboot-utils
package instead. This is what I did, so building it from source is left as an exercise for the reader. Either way, at the end you should have the vbutil_kernel
command available, and you should have the developer keys installed somewhere, which I’ll assume to be /usr/share/vboot/devkeys
.
Next, you need to build the bootloader. Check out the repo from Google:
$ git clone http://git.chromium.org/chromiumos/third_party/bootstub.git
Compiling it should be straightforward. It comes with a plain makefile, and if you’re not cross-compiling you should invoke it like this:
$ make PREFIX=""
This should result in a file called bootstub.efi
. This is your bootloader; put it somewhere you can find it.
Next, compile your kernel. Ideally, you should use your Chromebook’s original kernel config as a starting point. It’ll be at /proc/config.gz
when running ChromeOS or a Chrubuntu setup. Just gunzip that, copy it to .config
in your kernel tree, and do make oldconfig
or something.
Make a file called config.txt
containing the kernel command line you want to use. Whatever you’re using for Chrubuntu should work, just make sure you get your root filesystem right.
Now, to get from a kernel image to a signed kernel with bootloader, run this from the root of your kernel tree, adjusting for devkeys and bootstub locations, and arch, as appropriate.
$ vbutil_kernel --pack ./new_kern.bin --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --version 1 --config ./config.txt --vmlinuz ./arch/x86/boot/bzImage --bootloader /usr/src/bootstub/bootstub.efi
This should produce the file new_kern.bin
, which is your bootable kernel partition image. You can just dd
this directly onto your kernel partition.
You relly, really want to test this on a system running off a USB drive before trusting your internal drive with your new kernel. On a Chrubuntu install, pull out cgdisk
and examine the partition table: the Chrubuntu kernel partition should be the one labelled KERN-C
. Simply dd if=./new_kern.bin of=/dev/whatever-it-is
and reboot (remembering to make modules_install
first). If that doesn’t brick your Chrubuntu, it should be safe for use on your internal drive too.
First, figure out what your internal drive is called. Mine is /dev/mmcblk0
, although it could also be something like /dev/sda
. If in doubt, boot ChromeOS on it and run rootdev -s -d
in a shell. This should print the name of the device. I’ll assume it’s /dev/mmcblk0
from here on; substitute accordingly.
I used cgdisk
to make the partitions, but you could also use the cgpt
tool that comes with the VBoot package. You’ll need cgpt
to set the boot partition priority in either case.
Running cgdisk /dev/mmcblk0
should show you the current list of partitions. You’ll need to keep the R/W firmware partition (I’m assuming). It should be labeled as such (“RWFW”), and it’s partition 11 on my computer, but this may vary. cgdisk
reported it as the first partition in physical order. You’ll want to keep this, but delete the rest.
Create two kernel partitions, each with a size of 16Mb, and type 7f00
(“ChromeOS kernel”). Label the first one KERN-A
, and the second KERN-B
.
Partition your system as you please otherwise. I just made one big root partition, but you might want a swap partition as well if you can spare the disk space. I made my root partition of type 7f01
(“ChromeOS root”), but I don’t think this is necessary with a custom kernel.
You’ll have to update your config.txt
file with the correct root partition and rebuild the kernel boot image, then dd
it onto both of your kernel partitions. Keep the KERN-B
partition as a known working backup, and put your updated kernels only on KERN-A
from now on.
In order to tell the firmware to boot off KERN-A
, run the following command (assuming KERN-A
is partition number 1, otherwise adjust the -i
parameter accordingly):
$ cgpt add -i 1 -S 1 -P 5 /dev/mmcblk0
Now, install your system on the rest of the disk as you like - I just mounted my root filesystem, extracted an Arch base tarball into it, and went with the regular Arch install process from there, but you could also use debootstral
to install any Debian based system, etc. Make sure you don’t install Grub or any other kind of bootloader in the process, you don’t need any of those.
Reboot and hope for the best. If it doesn’t work, don’t panic, you’ve still got your USB drive to figure it out. Worst case, you can use a ChromeOS recovery image to get your ChromeOS back.