March 24, 2016 - Javier Martinez Canillas

Use a mainline U-Boot and non-signed kernels on Exynos Chromebooks

In a previous post, I explained how to boot a mainline Linux Kernel to use a standard distribution on a Samsung Chromebook by installing it in the unused KERN-C and ROOT-C partitions of the internal eMMC. The kernel binary was contained in a signed FIT image since the read-only vendor bootloader can only boot signed images.

The Many Ways to Boot Linux

This is only one of the approaches that can be used to boot a mainline kernel. Another technique is to boot a signed u-boot image instead of a kernel, this process is called chain loading since the bootloader loads another bootloader rather than an operating system kernel. Non-signed kernels can be booted by chain loading a signed u-boot; this makes development easier and is more aligned with the development process on ARM platforms that don’t require verified boot.

Another option would be to replace the stock vendor bootloader by disabling the SPI flash write protection and flash a mainline u-boot as explained in this Ach Linux forum thread. However, this is not recommended since flashing the wrong u-boot can brick the device, while keeping the read-only bootloader enables the ability to recover if things go wrong.

One final method this post will explain is installing a mainline u-boot, kernel and a Linux distribution in an external MMC/uSD card which is much safer since the internal eMMC that contains the stock ChromeOS doesn’t have to be modified.

For brevity, this article assumes you’ve already read the previous post because it  won’t cover background information about the Chromebook boot process, verified boot, and ChromeOS disk partition layout. It is highly recommended that you read the previous article if you are not already familiar with these concepts.

Enable Developer Mode to Boot From External Media

To boot the Chromebook from  external media, developer mode must be enabled.  Developer mode also gives access to a root shell which is needed for installation. The ChromiumOS wiki has instructions to enable developer mode for both Snow and Peach Pi/Pit.

Once the Chromebook is in developer mode, booting from external media must be enabled. This can be done by executing the following command in the ChromeOS root shell:

Prepare the uSD Card

The first step is to format the SD card with a partition layout that meets the Chromebook’s boot process expectations. Create a GPT partition table using the fdisk utility:

Use the g command to create a new empty GPT partition table and then the w command to write the table to disk and exit.

The Chromebook boot process relies on custom attributes in the GPT table, so the next step is to use the cgpt tool to create the partitions. Use the following script to create 3 partitions to store u-boot, boot files (kernel, device tree, etc), and the root filesystem.

The script takes the block device that will be used  as a parameter, and it must be run as root. Assuming the script is called, this is the command to execute:

You can use cgpt show to make sure the partitioning was correctly completed:

Build and Install U-boot

The next step is to build u-boot from source; clone the repo and checkout the latest tag, at the time of this article’s publication, the latest version is 2016.01:

For each board u-boot supports, there is a default configuration available. For example, the default configuration for the Exynos5250 Snow and Exynos5420 Peach Pit Chromebooks are snow_defconfig and peach-pit_defconfig respectively.

For this post I’ll build a u-boot and kernel for the Exynos5800 Peach Pi, so peach-pi_defconfig will be used:

Once the u-boot binary has been compiled, the next step is to generate a uImage that contains it. U-boot images have a header that contains the load and entry point addresses for the binary in the uImage payload, among other things. This should be set to the address of CONFIG_SYS_TEXT_BASE: the address against which u-boot is linked.

The address is platform or board dependent so the value has to be checked for the specific Chromebook. For the Exynos5800 Peach Pi:

However, the Exynos5250 Snow (and in fact all Exynos5250 boards) has a different address:

The mkimage tool is used to create a uImage for the u-boot binary and the correct load and entry addresses must be passed:

Now, the uImage needs to be be signed so the verified boot will be able to load and execute it. Use the vbutil_kernel utility to sign the image:

The signed image in this example is uboot.kpart, and it must be flashed to the partition that has the highest priority attribute because the bootloader will try to get a signed image from there:

Build and Install the Kernel

The next step is to build the Linux Kernel. At the time of this writing, the last version is v4.4 so download this version:

Now configure it using the Exynos default configuration, and build the kernel and device tree binaries:

Mount the SD boot and rootfs partitions, and copy the kernel image and Exynos5800 Peach Pi DTB:

Install a Rootfs

Download an ARMv7 rootfs to install in the SD card. For example you can download a tarball from the Arch Linux distribution:

Add a Boot Loader Spec File

Each board u-boot supports has a set of custom default boot commands and environment variables. This makes it challenging for distributions to have a standard image that can be used on different boards since each one has its own default configuration about where to fetch the kernel and dtb, the partition that’s as a root, etc.

Fortunately there has been some work to standardize the default boot commands and this effort is known as the u-boot distro commands. Basically, these are a set of standard commands and variables that can be used to search for bootable media and read a configuration files instead of having hardcoded values as defaults.

The configuration file follows mostly what is specified in the Freedesktop’s BootLoaderSpec. The u-boot documentation has a README.distro file that explains the distro commands in detail.

Copy the following BootLoaderSpec config file to the boot partition in a extlinux directory so the distro commands can fetch the kernel image and DTB that are stored in the boot partition:

The file has a single entry that specifies the path from which Linux and the DTB have to be loaded as well as the command line options that need to be appended to the bootargs variable so the kernel can use the rootfs partition as the root mount point.

The distro commands search for bootable partitions so mark the boot partition as bootable using the fdisk utility:

Use the x command to access to the extra functionality menu, then use the A command to toggle the legacy BIOS bootable flag and choose the boot partition number (2).

Next, press r to return to the main menu, and finally the w command to write the table to disk and exit.

Enjoy Mainline U-boot and Linux on your Chromebook

At this point the Chromebook should be able to boot both the mainline u-boot and Linux kernel. Insert the uSD card in the Chromebook and hit Ctrl + u, the mainline u-boot should be booted and the “Peach Pi MMC boot options” displayed for 20 seconds until the menu timeouts and the default entry “v4.4 mainline kernel” is used.

More boot options can be added by having different entries in the extlinux.conf file. This is very useful to test kernels during development but keep one that is known to work to make sure that the machine will always boot.

Happy hacking!

Javier Martinez Canillas

About Javier Martinez Canillas

Javier was a Senior Linux Kernel Developer for the Samsung Open Source Group. He has contributed to different kernel subsystems with a focus on ARM and Exynos SoC support. Besides hacking, he enjoys spending as much time as possible with his wife Tami and their twins, running, reading and writing technical articles like "Kbuild: the Linux Kernel Build System", published by the Linux Journal.

Image Credits: Köf3 - via Wikimedia Commons

Development / Linux Chromebook / Exynos / Samsung / U-Boot /


  • Michael says:

    I am using vboot-utils on Arch Linux Arm on a snow chomebook (i.e. no chromeos). How do I make/get devkeys so I can run this command “vbutil_kernel –pack uboot.kpart –keyblock /usr/share/vboot/devkeys/kernel.keyblock –signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk –version 1 –arch arm –config /tmp/config –vmlinuz uboot.img”

    • Javier Martinez Canillas Javier Martinez Canillas says:

      Hello Michael,

      Sorry for not answering before. Probably you already know the answer by now but there should be a vboot-kernel-utils (or named similar) package in arch that contains the vbutil_kernel utility and developer keys to sign images. I’m not an Arch user but these are certainly packaged in other distros (i.e: Debian and Fedora).

  • Michael says:

    Another question, is there any reason I shouldn’t compile uboot on my chromebook itself. I compiles just fine but I can’t test it (see above). I’m using GCC 5.3.0. More info –

    Target: armv7l-unknown-linux-gnueabihf
    Configured with: /build/gcc/src/gcc-5-20160209/configure –prefix=/usr –libdir=/usr/lib –libexecdir=/usr/lib –mandir=/usr/share/man –infodir=/usr/share/info –with-bugurl= –enable-languages=c,c++,fortran,go,lto,objc,obj-c++ –enable-shared –enable-threads=posix –with-system-zlib –with-isl –enable-__cxa_atexit –disable-libunwind-exceptions –enable-clocale=gnu –disable-libstdcxx-pch –disable-libssp –enable-gnu-unique-object –enable-linker-build-id –enable-lto –enable-plugin –enable-install-libiberty –with-linker-hash-style=gnu –enable-gnu-indirect-function –disable-multilib –disable-werror –enable-checking=release –host=armv7l-unknown-linux-gnueabihf –build=armv7l-unknown-linux-gnueabihf –with-arch=armv7-a –with-float=hard –with-fpu=vfpv3-d16

    Thanks for the great post, sorry I didn’t mention in first time round – I was too obsessed with trying to get mainline uboot running! Something I have been trying for ages without success. Now if you wouldn’t mind explaining how to add the appropriate blobs so I can flash mainline uboot to the RO flash… 😉 only joking… but I do really like to break things so maybe just PM me 🙂

    • Javier Martinez Canillas Javier Martinez Canillas says:

      Hello Michael,

      I’m glad that you liked the post.

      No, there is no reason why you shouldn’t compile u-boot natively in the target platform. I always cross-compile because I find it easy for self contained projects like U-boot or Linux that doesn’t have external dependencies.

      About flashing U-boot, I don’t really recommend it since you can chain load a non-verified u-boot so the user experience is the same but you can keep the original verified u-boot in case things go wrong. That way the device will never be bricked.

      But if you really want to do it, then you need to remove the screw that is the SPI flash write protection, and the use flashrom to disable write protection and flash the u-boot to the SPI.

      There are many articles that explain the process, for example:

  • Milan P. Stanić says:

    Helo Javier,
    I followed your guide and installed everything. u-boot doesn’t boot kernel but instead write error message: ** Invalid partition 12 **
    Do you have any idea what is wrong and why u-boot want partition 12, or how can that be changed in the u-boot source. (I searched net but can’t find anything usefull about problem)
    I can boot linux from external and internal mmc following your previous post (guide)

    • Javier Martinez Canillas Javier Martinez Canillas says:

      Hello Milan,

      The problem is that you seem to have previous default environment variables stored and have a boot command that tries to load from a partition 12.

      You can fix this by resetting the environment vars to the default and store that instead to overwrite the old ones.

      From the u-boot prompt execute the following commands:

      # env default -a
      # saveenv
      # boot

  • Michael says:

    Hi Javier,

    Thanks for your replies, and thanks again for the post as I have finally got mainline uboot on my chromebook 🙂

    You were right about the devkeys – I downloaded vboot-kernel-utils debian package and use the ones in there. The Arch Linux vboot package does not include the keys, and the vboot it provides also requires –bootloader to be passed as an option. This can just point to an empty file just like you do with –config .

Leave a Reply to Javier Martinez Canillas Cancel reply

Your email address will not be published. Required fields are marked *

Comments Protected by WP-SpamShield Anti-Spam