Difference between revisions of "User:Uli/Acer Chromebook R13 GPU test system"

From eLinux.org
Jump to: navigation, search
(Mainline kernel)
(Mainline kernel)
Line 176: Line 176:
= Mainline kernel =
= Mainline kernel =
A non-working forward-port of the R13-specific drivers to the mainline kernel can be found at https://github.com/uli/kernel/tree/elm-broken. It currently freezes with a blank screen at an unknown point. Hints on how to get a serial console on this device would be appreciated.
A functional forward-port of the R13-specific drivers to the mainline kernel can be found at https://github.com/uli/kernel/tree/elm-working. The basic features required to test a kernel (display, backlight, framebuffer console, keyboard, SD card and USB3.0 port) work; other things may or may not.
The build procedure is the same as for the vendor kernel, but there is currently no GPU support.
== Low-level debugging ==
== Low-level debugging ==

Latest revision as of 01:29, 29 September 2017

This page gives instructions on how to install a Debian userland system for the Chromebook R13, and how to compile a kernel with GPU support from source.


This will create a dual-booting environment where you can switch between booting Debian Linux ARM and the stock ChromeOS. No changes are made to the internal eMMC drive, and your new Linux install will run completely from external storage.

These instructions are intended to produce a system sufficient for testing GPU operation. There is no focus on the things a typical user would want, such as WiFi and a desktop environment. If you want those, you are on your own.


  • An Acer Chromebook R13.
  • An SD card.
  • A USB-to-Ethernet adapter (optional, but highly recommended).

You must be running the latest ChromeOS prior to installation.

The instructions for switching the Chromebook to developer mode and for preparing an SD card have been lifted wholesale from the ArchLinux ARM web site.

Switch to developer mode

  1. Turn off the laptop.
  2. To invoke Recovery mode, you hold down the ESC and Refresh keys and poke the Power button.
  3. At the Recovery screen press Ctrl-D (there's no prompt - you have to know to do it).
  4. Confirm switching to developer mode by pressing enter, and the laptop will reboot and reset the system. This takes about 10-15 minutes.

Note: After enabling developer mode, you will need to press Ctrl-D each time you boot, or wait 30 seconds to continue booting.

Enable booting from external storage

  1. After booting into developer mode, hold Ctrl and Alt and poke the T key. This will open up the crosh shell.
  2. Type shell to get into a bash shell.
  3. Type sudo su to become root.
  4. Then type this to enable USB booting:
    crossystem dev_boot_usb=1 dev_boot_signed_only=0
  5. Reboot the system to allow the change to take effect.

Create a root USB or SD for dual booting

Note: If you are performing this step on the Chromebook, it is highly recommended to use a USB SD card adapter for these steps when targeting a micro SD card. The ChromeOS kernel uses a high speed for the SD slot, which can cause many errors reading and writing to the card. The Linux kernel we build later lowers the speed to allow safe operation in the micro SD slot.

These instructions are written for installing to an SD card. This is recommended as it leaves the USB port free for other things, such as a USB-to-Ethernet adapter. The steps for preparing a USB drive are identical, however; only the device names have to be changed.

  1. If you are doing this on the Chromebook, get a root shell as described in the previous section.
  2. Many Linux systems, including ChromeOS, will automatically mount any partitions they find, so unmount everything now:
  3. umount /dev/mmcblk1*
  4. Start fdisk to create a GPT partition table:
  5. fdisk /dev/mmcblk1
  6. At the fdisk prompt:
    1. Type g. This will create a new empty GPT partition table.
    2. Write the partition table and exit by typing w.
  7. Partition the micro SD card:
  8. cgpt create /dev/mmcblk1
    cgpt add -i 1 -t kernel -b 8192 -s 65536 -l Kernel -S 1 -T 5 -P 10 /dev/mmcblk1
  9. To create the rootfs partition, we first need to calculate how big to make the partition using information from cgpt show. Look for the number under the start column for Sec GPT table which is 15633375 in this example:
  10. localhost / # cgpt show /dev/mmcblk1
           start        size    part  contents
               0           1          PMBR
               1           1          Pri GPT header
            8192       65536      1   Label: "Kernel"
                                      Type: ChromeOS kernel
                                      UUID: E3DA8325-83E1-2C43-BA9D-8B29EFFA5BC4
                                      Attr: priority=10 tries=5 successful=1
        15633375          32          Sec GPT table
        15633407           1          Sec GPT header
  11. Replace the xxxxx string in the following command with that number to create the root partition:
  12. cgpt add -i 2 -t data -b 73728 -s `expr xxxxx - 73728` -l Root /dev/mmcblk1
  13. Tell the system to refresh what it knows about the disk partitions:
  14. partx -a /dev/mmcblk1
  15. Format the root partition:
  16. mkfs.ext4 /dev/mmcblk1p2

Install a Debian armhf userland system

The ChromeOS system runs a 32-bit hardfloat userspace, and we need the binary-only libraries for GPU operation, so we need a compatible system.

These instructions assume that you are running a Debian-derived distribution.

  1. Install the packages debootstrap and qemu-user-static.
  2. Create a directory that you want to contain your new Debian system.
  3. Run debootstrap:
  4. qemu-debootstrap --arch armhf sid $TARGET_DIRECTORY http://deb.debian.org/debian/
  5. Wait.

Once the process has finished, you will have a very bare-bones Debian armhf system in $TARGET_DIRECTORY. Mount the root partition you have created on the SD card and rsync the contents of $TARGET_DIRETORY there.

Edit the file /etc/shadow and remove the asterisk in the line starting with root. That will allow you to log in as root on the console.

Build a kernel with GPU support


  1. If you are not running an ARM64 workstation, you need an ARM64 (aka aarch64) cross-toolchain.
  2. You need the u-boot mkimage tool and the ChromeOS verified boot utilities:
  3. apt-get install u-boot-tools vboot-kernel-utils

    Note: In older Debian versions, the vboot-kernel-utils package was built without support for non-native architectures, so if you are running a non-ARM system, you may have to manually install a version of this package from a later distribution.

  4. A number of files are required that can be found at the ArchLinux ARM PKGBUILDs repository in the subdirectory core/linux-oak:
  5. 0009-Downgrade-mmc1-speed.patch

Build Procedure

  1. Clone the ChromeOS kernel sources:
  2. git clone https://chromium.googlesource.com/chromiumos/third_party/kernel r13-kernel
  3. Switch to the chromeos-3.18 branch:
  4. cd r13-kernel
    git checkout chromeos-3.18
  5. Apply the MMC patch. This patch is very important. Without it, corruption of the root filesystem on the SD card is guaranteed.
  6. git am 0009-Downgrade-mmc1-speed.patch
  7. Set the cross-compiling environment variables.
  8. export ARCH=arm64
    export CROSS_COMPILE=aarch64-linux-gnu-

    You may have to amend the latter, depending on what toolchain you use.

  9. Configure the kernel. Copy the ArchLinux config file to .config (with a dot), then run make oldconfig.
  10. Enable the GPU driver. The config option is CONFIG_DRM_POWERVR_ROGUE_1_6.
  11. Build kernel, modules and device trees:
  12. make -j$VIEL Image modules dtbs
  13. Create a kernel partition image:
  14. mkimage -D "-I dts -O dtb -p 2048" -f kernel.its vmlinux.uimg
    dd if=/dev/zero of=bootloader.bin bs=512 count=1
    vbutil_kernel --pack vmlinux.kpart --version 1 --vmlinuz vmlinux.uimg --arch aarch64 --keyblock kernel.keyblock --signprivate kernel_data_key.vbprivk --config cmdline --bootloader bootloader.bin

Install the kernel and modules

  1. Install the generated kernel partition image to partition 1 of your SD card:
  2. dd if=vmlinux.kpart of=/dev/mmcblk1p1
  3. Install the kernel modules to the root file system on your SD card:
  4. make modules_install INSTALL_MOD_PATH=<mount point>

Booting the system on the Chromebook

  1. Unmount the SD card and remove it from your workstation.
  2. With the Chromebook turned off, insert the SD card.
  3. Turn the Chromebook on.
  4. At the "OS verification disabled" screen, press Ctrl-U. (Works for both USB drives and SD cards.)

After a few seconds, you should be greeted with a login screen (and some random kernel messages).

Install development tools

In order to install more software, you need a network connection, so connect the USB-to-Ethernet adapter.

  1. Run dhclient.
  2. Run apt-get update.
  3. Install a number of packages:
    1. Development essentials:
    2. apt-get install gcc libgles2-mesa-dev libgbm-dev git autoconf automake libtool pkgconf make
    3. Convenience:
    4. apt-get install net-tools rsync less $YOUR_EDITOR

Rip the binary blobs from ChromeOS

  1. Mount the ChromeOS system partition:
  2. mount -o ro /dev/mmcblk0p3 /mnt
  3. Copy the firmware blobs for various devices:
  4. rsync -a /mnt/lib/firmware/ /lib/firmware/

    A reboot may be required to make sure the new firmware files are loaded correctly.

  5. Copy the DRI driver:
  6. mkdir /usr/lib/dri
    cp -p /mnt/usr/lib/dri/pvr_dri.so /usr/lib/dri
  7. Rsync the userspace libraries:
  8. mkdir /pvrlibs
    rsync -a /mnt/usr/lib/lib{EGL,GLESv2,dbm,gbm,glslcompiler,minigbm,nettle,pvr_dri_support,srv_um,usc}.so* /pvrlibs/

This allows you to use the GPU by running your program like this:

LD_LIBRARY_PATH=/pvrlibs <binary>

Alternatively, you can copy the libraries to /usr/lib and do away with the explicit library path, but that may get you in trouble when updating packages.

Another possibility is not to copy the files and to simply point the library path to the ChromeOS partition. That works with trivial examples, but is likely to break with anything substantial.

Mainline kernel

A functional forward-port of the R13-specific drivers to the mainline kernel can be found at https://github.com/uli/kernel/tree/elm-working. The basic features required to test a kernel (display, backlight, framebuffer console, keyboard, SD card and USB3.0 port) work; other things may or may not.

The build procedure is the same as for the vendor kernel, but there is currently no GPU support.

Low-level debugging

There is an on-board USB hub to which the external USB 3.0 port is connected, and it can be enabled and disabled using GPIO 118. (The firmware source code says "reset", but similar chips by the same manufacturer do not have a reset pin, so I suspect the GPIO just switches the power supply on and off.)

The firmware turns the hub on, which pulls the D- pin of the USB 3.0 port low. The kernel does not touch pin 118, so the hub remains in that state. When the hub is turned off, D- is pulled to 3.3V. So if one adds code anywhere in the kernel that writes 0x40 to 0x10005478, D- will go high if it has been executed, and remain low otherwise.

This behavior is independent of the state of the other USB hardware, and the method works just as well in head.S as it does in any driver.

There is a substantial delay between turning the hub on again (write 0x40 to 0x10005474) and D- going low, which is what makes me suspect that the reset is not a "real" reset but a power cycle. For practical purposes, this makes it more or less impossible to bit-bang serial data out of D-, but a slow (1 Hz) blink is possible.