Recently, there have been new Skylake-based Chromebooks based on two development boards, namely Glados and Kunimitsu. These Chromebooks are particularly interesting to use as a Linux laptop because of the decent hardware you get for the price, the build quality of most of these Chromebooks and because ChromeOS is based on Linux Gentoo. In this tutorial, we will mostly be focusing on installing Linux Gentoo and Funtoo on these Chromebooks, but these instructions can also be applied to other distributions.
We will consider the following Glados-based devices:
- Samsung Chromebook Pro (Caroline)
- HP Chromebook 13 G1 (Chell)
- ASUS Chromebook Flip C302 (Cave)
and the following Kunimitsu-based devices:
- Thinkpad 13 Chromebook (Sentry)
- Chromebook 14 for work (CP5-471) (Lars)
- Dell Chromebook 13 3380 (Asuka)
If you have another Skylake-based Chromebook not mentioned here, but that is based on Glados or Kunimitsu (see https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices), then it is very likely that these instructions will work for you as well.
The current status for these Chromebooks is as follows:
- Internal storage (eMMC)
- Internal keyboard
- Jack detection
nau88l25_max98357a(Asuka, Cave, Lars, Sentry)
- Jack detection
Note: while audio does work for me, it does not seem to work for everyone. The issues are being tracked at https://github.com/GalliumOS/galliumos-distro/issues/379. Furthermore, audio is not yet in a perfect state as PulseAudio does not know how to transition between speakers and headphones. I will update this post in the future as this issue progresses into a proper solution.
In order to get access to a shell, we'll have to switch the device to developer mode:
- Turn off the laptop.
- Whilst holding the Escape and the Refresh key, poke the Power key to invoke recovery mode.
- Once the recovery screen appears, press the Control and D keys.
- Confirm switching to developer mode by pressing the Enter key. The laptop will now reboot and prepare the system for developer mode. This process will commonly take about ten to twenty minutes.
If all went well, developer mode should now be enabled. In order to boot ChromeOS, you'll now have to press the Control and D keys to confirm that you want to boot from the SSD.
The boot process of Chromebooks is somewhat more complicated than the boot process of x86 devices (BIOS and UEFI) and ARM devices (u-boot). Similar to these devices, some Chromebooks do use the same firmware and boot loaders, but in a more extensive fashion. Despite the fact that there are still some legacy Chromebooks that use a BIOS for x86 and u-boot for ARM, Coreboot seems to be the firmware of choice for most of the Chromebooks.
One of Google's major considerations during the design of the boot process has been the concern of trust. When booting up the Chromebook, the first component that will be turned on is the CPU. The CPU will then load and execute the various boot loader stages that have been burnt into the ROM accompanying the CPU. The goal of these boot loader stages is to initiate certain parts of the CPU, and load the firmware from the ROM that has been soldered onto the motherboard. This ROM is split up into a read-only section and a read-write section, where the prior verifies the latter before loading and executing it. For most Chromebooks, this ROM will contain Coreboot, as well as some payload such as Depthcharge, or u-boot in the case of older Chromebooks. This payload will then determine what kernel to boot from the disk by inspecting the GPT partitions. Once a kernel has been chosen, it will be verified and loaded by the payload. Alternatively, some Chromebooks ship with SeaBIOS as a payload, but since there might be some fixes required, you may have to update it. See https://mrchromebox.tech/ for more information about this. We will instead use the existing Depthcharge payload to boot our self-signed images.
The verification process is part of the verified boot (vboot) specification and implementation. This process mostly relies on cryptography, where a private and a public key are used for signing (encrypting the kernel) and verification (decrypting the kernel) respectively. Fortunately, this verification process can be disabled, in which case the developer keys can be used to sign your own kernel images.
Let's disable this verification process:
- Boot into ChromeOS and switch to a different tty using Ctrl + Alt + F2 (Forward key).
shellto get into a bash shell.
sudo suto become root.
crossystem dev_boot_usb=1 dev_boot_signed_only=0to enable booting from external media, and to disable the boot verification process.
- Reboot the system to allow the changes to take effect.
After the changes have taken effect, it should now be possible to boot from external media using the Ctrl + U keys.
To sign the images, partition the storage device, communicate with the microcontroller behind CrosEC, we will need various tools. To install these tools on Linux Gentoo or Linux Funtoo, you can use the ebuilds from my overlay.
First create a file called
/etc/portage/repos.conf/synkhronix.conf as follows:
[synkhronix] location = /usr/local/overlay/synkhronix sync-type = git sync-uri = https://git.codentium.com/StephanvanSchaik/gentoo-overlay.git auto-sync = yes
Next we fetch the overlay and update the
emerge --sync eix-update
Then we can install the tools as follows:
emerge -av vboot-utils mosys
Partitioning the SD-card
To start with running Linux Gentoo or Funtoo, I recommend to keep your installation on an external storage medium such as a USB drive or SD-card first. Furthermore, I also recommend using an existing Linux system to set up the USB drive or SD-card, as the ChromeOS system is quite cumbersome to use without something like crouton.
At minimum, we'll only need a kernel partition and a rootfs partition. First, we'll reserve 64 kiB for the kernel partition and the remaining storage for the rootfs using
sys-apps/gptfdisk if you haven't installed it already:
emerge -av gptfdisk
Then we can set up the partitions, assuming that your storage device is named
/dev/mmcblk1 and the first partition is named
/dev/mmcblk1p1 (please change these to the appropriate names):
- Press the O key to start with an empty partition lay-out.
- Press the N key to create a new partition.
- Press the Enter key to use the default offset.
+64Mand press the Enter key to create a 64M partition.
7f00and press the Enter key to assign the ChromeOS kernel partition type.
- Press the N key to create a new partition.
- Press the Enter key three times to use the default offset, size and partition type.
- Press the W key to save the changes to the disk.
Next we mark the kernel partition as bootable using
cgpt add -i 1 -t kernel -S 1 -T 5 -P 10 /dev/mmcblk1p1
Once the changes have been saved, we can format the rootfs partition as an Ext4-filesystem:
Finally, we can mount the partition and install the root filesystem and the Portage package manager by downloading and extracting the stage3 and Portage tarballs respectively:
mkdir -p /mnt/gentoo mount /dev/mmcblk1p2 /mnt/gentoo wget -O - http://distfiles.gentoo.org/releases/amd64/autobuilds/$(wget -O - http://distfiles.gentoo.org/releases/arm/autobuilds/latest-stage3-amd64.txt 2>/dev/zero | tail -n1) | tar xjp -C /mnt/gentoo/ wget -O - http://distfiles.gentoo.org/releases/snapshots/current/portage-latest.tar.bz2 | tar xjp -C /mnt/gentoo/usr/
Alternatively, if you want to use Linux Funtoo, you can set it up as follows:
mkdir -p /mnt/gentoo mount /dev/mmcblk1p2 /mnt/gentoo wget -O - http://build.funtoo.org/funtoo-current/x86-64bit/generic_64/stage3-latest.tar.xz | tar xJp -C /mnt/gentoo/
Finally, you can also copy an existing rootfs from an existing system, as long as it has been compiled for the same architecture:
mkdir -p /mnt/gentoo mount /dev/mmcblk1p2 /mnt/gentoo cp -ax / /mnt/gentoo
Building a Linux kernel
The mainline support for Chromebooks has improved much in the past few years. Therefore we will opt to build a mainline kernel for our Chromebook.
sys-kernel/gentoo-sources and emerge the latest Gentoo kernel source:
echo "sys-kernel/gentoo-sources ~amd64" >> /etc/portage/package.keywords emerge -av gentoo-sources
/usr/src/linux and download the following kernel configuration to get some sane defaults for your Chromebook:
cd /usr/src/linux wget https://git.codentium.com/StephanvanSchaik/gentoo-chromebook-skylake/raw/master/linux/skylake-config -O .config
Next, update the config to be compatible with the current version of your Gentoo kernel sources:
This configuration can be further fine-tuned using
make menuconfig, but it should already be fine for our needs. Build the kernel and the modules as follows:
make -j4 bzImage modules
INSTALL_MOD_PATH=/mnt/gentoo make modules_install
Then we have to create an empty
boot.txt file and set up the kernel cmdline arguments in
echo "console=tty0 rootwait rw root=/dev/mmcblk1p2" > cmdline echo " " > boot.txt
Finally, we can sign the image using
vbutil_kernel --pack kernel.kpart --keyblock /usr/share/vboot/devkeys/kernel.keyblock --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk --version 1 --vmlinuz arch/x86/boot/bzImage --bootloader boot.txt --config cmdline --arch x86_64
Now that it has been signed, write it to the kernel partition on your SD-card:
dd if=kernel.kpart of=/dev/mmcblk1p1
Now that the SD-card is ready, you can try booting it on the Chromebook.
The relevant kernel config options for networking are:
Device Drivers ---> [*] Network device support ---> [*] Wireless LAN ---> <M> Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) <M> Intel Wireless WiFi DVM Firmware support <M> Intel Wireless WiFi MVM Firmware support
Make sure that
CONFIG_IWLWIFI is set to compile as a kernel module, as you will otherwise have to embed the Intel WiFi firmware into your kernel.
Next, we have to install
wpa_supplicant in order to be able to use WiFi:
emerge -av dhcpcd wpa_supplicant
Then add these services to automatically start up:
rc-update add dhcpcd default rc-update add wpa_supplicant default
Finally, edit your
/etc/wpa_supplicant/wpa_supplicant.conf to contain the settings for the networks you want to be able to connect to.
If you like a more GUI-oriented approach, you might be interested in using
The relevant kernel config options for the touchpad and the touchscreen are:
Device Drivers ---> Input device support ---> [*] Mice ---> <M> ELAN I2C Touchpad support [*] Enable I2C support [*] Enable SMbus support [*] Touchscreens ---> <M> Elan eKTH I2C touchscreen I2C Support ---> -*- I2C bus multiplexing support I2C Hardware Bus support ---> <*> Synopsys DesignWare Platform [*] Synopsys DesignWare Slave <*> Synopsys DesignWare PCI -*- I2C slave support -*- Pin controllers ---> <*> Intel Sunrisepoint pinctrl and GPIO driver -*- GPIO Support ---> HID Support ---> <*> Generic HID driver I2C HID support ---> <*> HID over I2C transport layer
Then set up the following input devices in
/etc/portage/make.conf for X11:
INPUT_DEVICES="evdev libinput synaptics"
Other than not being able to use multi-touch gestures, these should work out of the box.
The relevant kernel config options for audio are:
Device Drivers ---> I2C Support ---> -*- I2C bus multiplexing support I2C Hardware Bus support ---> <*> Synopsys DesignWare Platform [*] Synopsys DesignWare Slave <*> Synopsys DesignWare PCI -*- I2C slave support -*- Pin controllers ---> <*> Intel Sunrisepoint pinctrl and GPIO driver -*- GPIO Support ---> <*> Sound card support ---> <*> Advanced Linux Sound Architecture ---> <*> ALSA for SoC audio support ---> <M> Intel ASoC SST drivers <M> Intel ASoC SST driver for SKL/BXT/KBL/GLK/CNL -M- Intel Audio machine drivers <M> ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode <M> ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode
In order to be able to get the ALSA drivers to work, you will need an ALSA topology firmware blob. The blob can be found at https://git.codentium.com/StephanvanSchaik/gentoo-chromebook-skylake/lib/firmware. Download it to
wget https://git.codentium.com/StephanvanSchaik/gentoo-chromebook-skylake/raw/master/lib/firmware/dfw_sst.bin -O /lib/firmware/dfw_sst.bin
If you boot up the Chromebook with functional audio, you should see something like the following in your
[ 4.368172] nau8825 i2c-10508825:00: No 'mclk' clock found, assume MCLK is managed externally [ 4.380909] snd_soc_skl 0000:00:1f.3: bound 0000:00:02.0 (ops i915_audio_component_bind_ops) [ 4.419973] HDMI HDA Codec ehdaudio0D2: Max dais supported: 3 [ 4.426297] snd_soc_skl 0000:00:1f.3: Direct firmware load for 9d70-CORE-COREBOOT-0-tplg.bin failed with error -2 [ 4.426299] snd_soc_skl 0000:00:1f.3: tplg fw 9d70-CORE-COREBOOT-0-tplg.bin load failed with -2, falling back to dfw_sst.bin [ 4.429631] snd_soc_skl 0000:00:1f.3: ASoC: Parent card not yet available, widget card binding deferred [ 4.460998] HDMI HDA Codec ehdaudio0D2: hdac_hdmi_present_sense: disconnect for pin:port 5:0 [ 4.461109] HDMI HDA Codec ehdaudio0D2: hdac_hdmi_present_sense: disconnect for pin:port 6:0 [ 4.461220] HDMI HDA Codec ehdaudio0D2: hdac_hdmi_present_sense: disconnect for pin:port 7:0 [ 4.461416] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> System Pin mapping ok [ 4.461445] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> System Pin mapping ok [ 4.461473] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> Reference Pin mapping ok [ 4.461497] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> DMIC Pin mapping ok [ 4.461522] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> HDMI1 Pin mapping ok [ 4.461547] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> HDMI2 Pin mapping ok [ 4.461577] skl_n88l25_m98357a skl_n88l25_m98357a: snd-soc-dummy-dai <-> HDMI3 Pin mapping ok [ 4.461589] skl_n88l25_m98357a skl_n88l25_m98357a: HiFi <-> SSP0 Pin mapping ok [ 4.462890] skl_n88l25_m98357a skl_n88l25_m98357a: nau8825-hifi <-> SSP1 Pin mapping ok [ 4.462900] skl_n88l25_m98357a skl_n88l25_m98357a: dmic-hifi <-> DMIC01 Pin mapping ok [ 4.462909] skl_n88l25_m98357a skl_n88l25_m98357a: intel-hdmi-hifi1 <-> iDisp1 Pin mapping ok [ 4.462917] skl_n88l25_m98357a skl_n88l25_m98357a: intel-hdmi-hifi2 <-> iDisp2 Pin mapping ok [ 4.462926] skl_n88l25_m98357a skl_n88l25_m98357a: intel-hdmi-hifi3 <-> iDisp3 Pin mapping ok
emerge -av alsa-utils alsa-lib pulseaudio
In addition, you will also need to set up ALSA UCM profiles in order to be able to switch between the speakers and the headphones.
The UCM profiles can be found at https://git.codentium.com/StephanvanSchaik/gentoo-chromebook-skylake/src/master/usr/share/alsa/ucm.
Clone the Git repository and copy them to
git clone https://git.codentium.com/StephanvanSchaik/gentoo-chromebook-skylake cp -r gentoo-chromebook-skylake/usr/share/alsa/ucm/* /usr/share/alsa/ucm/
Next depending on your device, you might have to create a symbolic link to the appropriate folder:
- For Caroline, run:
ln -s /usr/share/alsa/ucm/Google-Caroline-1.0-Caroline/ /usr/share/alsa/ucm/sklnau8825adi
- For Chell, run:
ln -s /usr/share/alsa/ucm/Google-Chell-1.0-Chell/ /usr/share/alsa/ucm/sklnau8825adi
- For Cave, run:
ln -s /usr/share/alsa/ucm/Google-Cave-1.0-Cave/ /usr/share/alsa/ucm/sklnau8825max
- For Sentry, run:
ln -s /usr/share/alsa/ucm/Google-Sentry-1.0-Sentry/ /usr/share/alsa/ucm/sklnau8825max
- For Lars, run:
ln -s /usr/share/alsa/ucm/Google-Lars-1.0-Lars/ /usr/share/alsa/ucm/sklnau8825max
- For Asuka, run:
ln -s /usr/share/alsa/ucm/Google-Asuka-1.0-Asuka/ /usr/share/alsa/ucm/sklnau8825max
Once booted up, run the following to use the speakers (replace
sklnau8825adi if your device uses
alsaucm -c sklnau8825max set _verb HiFi set _enadev Speaker
To use the headphones, run:
alsaucm -c sklnau8825max set _verb HiFi set _enadev Headphone
It is best to make sure you are not playing any audio using PulseAudio while switching between one of the two, as it will break the playback for running PulseAudio clients. Inserting a headphone in the jack works, but will also cause the playback to break for running PulseAudio clients. It is recommended to wait about five seconds after switching for the device to initialise properly. Hopefully, this will improve in the future. Unfortunately, this also affects jack detection. While ACPI events are registered whenever a headphone jack is plugged in or out, PulseAudio does not know how to handle these properly.