SurfaceRT

Wiki about running Ubuntu on the ARM (32-bit) Microsoft Surface RT/Surface 2 and related Windows RT devices.

For more info see: The Open Surface RT Home

Download

Your options are:

Although it is technically possible to install the full Ubuntu Desktop via Ubuntu Server/netboot, it is highly recommended that you install one of the lighter desktops such as Lubuntu, Xubuntu or MATE.

The above media need to be adapted for Windows RT devices and this is described below.

Surface Models

Many Surface 2 owners are unaware they have a Surface 2 because both machines are labelled with 'Surface/Windows RT' under the kickstand! If your device has a black rear then you have the Tegra 3 (T30) based Surface RT, but if it is silver grey then you have the Tegra 4 (T114) based Surface 2. It is important you know your model so that you can use the correct Device Tree Blob (DTB). This page makes a distinction between the two machines as they boot Linux differently, so follow the instructions for your device.

  • Surface RT - black
  • Surface 2 - silver

Secure Boot

There is no doubt that secure boot has been a major hurdle in putting Linux on Windows RT devices. Thankfully we now have a number of workarounds available to us:

  • For Tegra 3 based devices there is the USB tethered Fusée Gelée exploit. This removes all the restrictions of the UEFI firmware. Also known as APX booting.
  • Golden keys has been available since late 2016. It allows a self-signed Windows boot manager app to run and in turn an UEFI app such as GRUB 2. Secure boot and memory TrustZone are still active.

  • Yahallo is a new (2020) Tegra exploit that effectively turns off secure boot permanently. It can be applied with the help of golden keys. TrustZone is still active, but recent changes to the Linux kernel (~5.11) allowed this to be automatically avoided.

Consequently, the Surface RT has two boot options: APX or UEFI. APX currently offers considerably better performance, but it has the disadvantage of always needing "jump leads". Due to its added complexity it is discussed at the end of this page. The Surface 2 can only use UEFI. For UEFI booting it is recommended to install yahallo.

Microsoft patched the golden keys exploit, but fortunately for Tegra devices this can be reversed. The easiest way is to download and install the official 8.1 recovery image for you device as these pre date the patch. You must download an image as the recovery partition will not work for this.

Once you have a completely fresh install you can use the jailbreak usb to install golden keys and then run yahallo. Finally, remove golden keys if you intend to dual boot Windows or install Windows at a later date.

Custom Kernel

Ubuntu's generic kernel can be booted with APX when paired with a suitable DTB. However, a custom kernel gives greater hardware support (e.g. the touch/type covers). UEFI booting requires a custom kernel.

For kernel source, compiling and pre-built binaries please see here with the latest kernel binaries usually to be found here.

Pre-built binaries usually come in three parts: the kernel image called zImage or vmlinuz, a zipped folder containing extra kernel modules (e.g. for wifi), and a Device Tree Blob that exactly matches your model and boot method:

  • Surface RT booted via APX - tegra30-microsoft-surface-rt.dtb
  • Surface RT booted via UEFI - tegra30-microsoft-surface-rt-efi.dtb
  • Surface 2 - tegra114-microsoft-surface-2.dtb

Please ensure you download image, modules and dtb from the same kernel version number/date.

UEFI Booting

UEFI bootloaders need to be placed on the internal eMMC or USB drive. The root filesystem can be placed on eMMC, USB or microSD card.

Surface RT

The Surface RT can use GRUB 2 or UEFI shell as a bootloader. Pre-built '.efi' binaries are available by following the links. These are usually stored in an efi folder on the boot partition of a drive. On a USB drive they are normally given the name /EFI/Boot/bootarm.efi as this is the fallback file loaded by UEFI.

Unfortunately a bug with the Surface RT's UEFI implementation stops the display from working with most efi applications unless specifically patched (or the EfiFileChainloader is used). Touch and Type Covers also do not work on the Surface RT in these applications. Consequently, configuration files are used to automate booting and pass kernel command line parameters:

  • grub.cfg (GRUB 2)
  • startup.nsh (UEFI shell)

Sadly Ubuntu's version of GRUB 2 has an additional problem (fails to boot Linux) and should be avoided [bug report needed].

Putting the custom kernel and bootloader files together, the following files need to be added to installation media to boot on the Surface RT:

.
├── EFI
│   └── Boot
│       └── bootarm.efi
├── grub.cfg or startup.nsh
├── tegra30-microsoft-surface-rt-efi.dtb
└── zImage

For booting Ubuntu Server from a USB drive a simple grub.cfg may look like this:

linux /zImage root=/dev/sda2 cpuidle.off=1 net.ifnames=0 rootwait
initrd /initrd.img
devicetree /tegra30-microsoft-surface-rt-efi.dtb
boot

A startup.nsh may look like this:

fs0:
zImage dtb=tegra30-microsoft-surface-rt-efi.dtb root=/dev/sda2 cpuidle.off=1 net.ifnames=0 rootwait initrd=initrd.img

# shutdown if something went wrong
reset -s

Surface 2

NOTE: Booting Linux on the Surface 2 is still a work in progress.

The display and type/touch covers work as expected in GRUB 2/shell on the Surface 2, but there are new issues:

  • BUG#1 in Surface 2's UEFI firmware: BootServices->LoadImage causes a 7 minute wait when you want to load an EFI file that was compiled with anything other than edk2.

  • BUG#2 You can't shutdown the device with an UEFI call. This doesn't have to be implemented in the UEFI firmware, but it's a downgrade from the Surface RT which supports shutting down with a UEFI RuntimeServices call. (Surface 2 only supports reboot)

Unfortunately booting the Linux kernel through GRUB 2/shell incurs this 7 minute delay. However, we can avoid this delay if we boot the Linux kernel using the golden key test files. Something needs to give the kernel command line parameters and for this the Surface 2 kernel has recently been patched to read cmdline.txt.

Users maybe familiar with cmdline.txt from the Raspberry Pi. It performs a similar role for the Surface 2, but unlike the Pi the dtb and initrd (if required) are also specified in cmdline.txt.

You may already have the necessary golden key test files, but if you don't then download grub.zip from the XDA forum. The version of GRUB is very old and not particularly useful, but we can make use of the other files in the zip.

1. From the zip put the efi folder and test.efi onto a USB drive.

2. Download a Surface 2 kernel and Device Tree Blob. Put these also on the USB drive. Rename zImage to boot.efi

3. If you are using an initrd then put that on the USB drive.

4. Create a text file called cmdline.txt (watch out in Windows you don't end up with a file called cmdline.txt.txt!). In this put your command line parameters. For example for netboot:

dtb=tegra114-microsoft-surface-2.dtb cpuidle.off=1 initrd=initrd-with-wifi.gz 

The Surface 2 will happily boot from a usb drive, but currently looses usb power after the initrd and kernel are loaded. You can get around this if you have a usb hub that provides back power. Alternatively, place the root filesystem on a SD card (note, early Surface 2 kernels had the SD card slot configured to act as a serial port). The cmdline.txt will need to be adjusted for this, e.g. for Ubuntu Server:

dtb=tegra114-microsoft-surface-2.dtb  root=/dev/mmcblk1p2 cpuidle.off=1 net.ifnames=0 initrd=initrd.img rootwait 

The eMMC, touch/type covers, speakers and touchscreen work. WiFi works when you copy the kernel modules across to your rootfs. Something goes wrong with the screen on around a third to a half of boots. When this occurs you won't see boot messages and unless you've installed a desktop, you'll end up with a blank screen. If this happens press the power button to initiate power down and then after a few seconds hold the power button down to force power off. The Raspberry Pi OS desktop with its fbturbo driver seems to always work.

The Surface 2's eMMC only seems to work with a GPT partition table (it is blank on a reboot when formatted as MBR). This means you cannot directly copy a whole raspberry pi image to eMMC.

Ubuntu Server

Write the Ubuntu Server image to a USB drive following standard Raspberry Pi instructions. Copy the appropriate kernel zImage and dtb to the first (called "system-boot") partition on the USB drive. Add the appropriate bootloader/efi files to the same partition.

The default Raspberry Pi cmdline.txt uses net.ifnames=0 so add that to the surface kernel command line (list of kernel parameters).

The server image expects a working network on first boot, so setup as described here. Comment out or delete the ethernet stanza in the network-config file and use "mlan0" instead of "wlan0" for the built-in wireless.

version: 2
#ethernets:
#  eth0:
#    dhcp4: true
#    optional: true
wifis:
  mlan0:
    dhcp4: true
    optional: true
    access-points:
      "your-wifi-name":
        password: "your-wifi-password"

Unzip the kernel lib folder and copy the modules to the second (called "writable") partition:

sudo cp -r lib/modules /media/YOUR-USER-NAME/writable/lib/

Netboot

The netboot or mini iso installer is a small text based installer. It essentially consists of a kernel image and an initrd file that is loaded into ram on boot. Users have complete control of where and how the system is installed. You will be given a choice of desktops to install (or just a command line interface if preferred).

The initrd contains the kernel modules for Ubuntu's generic kernel, but we can add wifi modules and firmware for our custom kernels: (this assumes you've unzipped the lib folder holding the kernel modules)

wget http://ports.ubuntu.com/dists/focal/main/installer-armhf/current/legacy-images/generic/netboot/initrd.gz
mkdir /tmp/d-i_wifi
cp -r lib /tmp/d-i_wifi
cd /tmp/d-i_wifi
mkdir lib/firmware
cp -r /lib/firmware/mrvl lib/firmware
pax -x sv4cpio -w lib | gzip -c >wifi.cpio.gz
cd -
cat initrd.gz /tmp/d-i_wifi/wifi.cpio.gz > initrd-with-wifi.gz

The built in marvell wifi doesn't seem to get recognised as wifi by the installer ('unknown interface'). To get the internal wifi working you need to drop to a shell in the installer (use the 'Go back' option until you hit a menu with this option) and setup /etc/wpa_supplicant.conf (see here) and then run:

wpa_supplicant -B -i mlan0 -c /etc/wpa_supplicant.conf -D nl80211

Exit and select mlan0 at the network stage. You should have network. /etc/netplan/01-netcfg.yaml seems to think it is ethernet. You will have to edit this on the target system to have wifi. Make sure the target system has wpasupplicant as a cli only install may not have this.

You will have to choose the manual partitioning option. Do not use the automatic partitioning scheme as this will use a MBR partition table when the disk is cleared. There is no option to select a GPT partition table except through preseeding.

d-i partman-partitioning/default_label select gpt

The bootloader install will fail as the installer knows nothing about Windows RT devices. You will have to do this manually. flash-kernel-installer disables initramfs so you will have to reverse this if you want one.

Dual Booting

Making space for Ubuntu

If you need to shrink a windows partition to make space for Ubuntu then it is best to do this in Windows. Just search for 'partition' and open disk partition manager. From there you can shrink a partition. In Linux, bitlocker stops this working using the usual tools.

Available Boot Managers

GRUB 2

On the Surface RT you can have a dual-boot setup with GRUB 2 very much like a normal PC. However, a USB keyboard is normally needed to make a selection or edit entries. This fork of GRUB 2 changes the timeout behaviour to allow selecting an OS using the volume buttons only.

Before copying GRUB 2 to the eMMC make sure you have a working menu by doing a trial boot from USB. A sample grub.cfg is below (Ubuntu on microdSD card). For a menu you also need a font file (e.g. font.pf2). This can be found on any Ubuntu iso or installation with GRUB 2.

if loadfont /font.pf2 ; then
        set gfxmode=auto
        insmod efi_gop
        insmod efi_uga
        insmod gfxterm
        terminal_output gfxterm
fi

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray

set timeout=5
menuentry "Start Linux" {
        set gfxpayload=keep
        linux /zImage root=/dev/mmcblk1p2 cpuidle.off=1
        devicetree /tegra30-microsoft-surface-rt-efi.dtb
}
menuentry "Start Windows" {
        search --no-floppy --label --set SYSTEM
        chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
menuentry "Boot from next volume" {
        exit
}
menuentry "System restart" {
        echo "System rebooting..."
        reboot
}
menuentry "System shutdown" {
        echo "System shutting down..."
        halt
}

The above Windows entry searches for a filesystem with the label "SYSTEM" (which is the efi partition on the Surface RT) and sets root to that partition. You must set the root before the chainloader command. If you think SYSTEM is too generic you can instead search for the fs-uuid or the bootmgfw.efi file, or set the root directly:

menuentry "Start Windows" {
        set root=(hd0,2)
        chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}

Once you are happy that your menu works you can copy GRUB 2 to the eMMC and make it the default boot manager. In Windows open an Admin command prompt by right clicking on the start menu and selecting the appropriate menu item. Mount the efi partition with the drive letter b:

mountvol b: /s

Copy grub.efi, grub.cfg, font.pf2 and any other boot files you might need to the root of the eMMC's efi boot partition. The zImage, dtb and initrd doesn't have to be placed on the efi partition, but you may wish to put them there for simplicity. To copy the files from drive f:

copy f:\grub.efi b:
copy f:\grub.cfg b:
copy f:\font.pf2 b: 

Once you are finished remove the drive letter mapping:

mountvol b: /d

With bcdedit (from a Windows Admin command prompt) you could create a new bootmgr entry and change the default, but it is easier to just edit the existing entry:

bcdedit /set {bootmgr} path \grub.efi

To revert (or if something goes wrong), delete the file grub.efi on the eMMC and the fallback bootarm.efi (which should be the windows boot manager) will be booted.

Windows Metro (Touchscreen) Boot Manager

Here again we can make use of the golden key's 'test.efi' file. Unusually, we can actually boot Linux from the Windows boot manager! This is because test.efi is not an efi application, but a Windows boot manager application. It chainloads an efi application called 'boot.efi'. The latter is what we need to call our true efi application and for the Surface 2 this is what zImage needs to be called.

Copy test.efi, boot.efi and any other needed files to the eMMC's efi partition (see above for how to do this from Windows).

Use bcdedit from a Windows Admin command prompt to add a new entry (the entry must have nointegritychecks). If you are not familiar with bcdedit type:

bcdedit /?

To list all entries:

bcdedit /enum all

Create a new bootapp entry for Ubuntu:

bcdedit /create /d "Ubuntu Server" /application bootapp
bcdedit /set {the-big-long-number-id-you've-been-given} device boot
bcdedit /set {the-big-long-number-id-you've-been-given} path \test.efi
bcdedit /set {the-big-long-number-id-you've-been-given} locale en-GB
bcdedit /set {the-big-long-number-id-you've-been-given} nointegritychecks Yes

Now add it to the display order:

bcdedit /displayorder {the-big-long-number-id-you've-been-given} /addlast

Upon reboot you should be presented with the boot manager.

Windows Legacy (Text) Boot Manager

This offers a faster boot time. Unlike the Surface RT, the Surface 2 has working touch/type cover in the legacy boot manager.

From an Windows Admin command prompt run one of the following commands (it doesn't matter which):

bcdedit /set {current} bootmenupolicy Legacy

or

bcdedit /set {bootmgr} displaybootmenu Yes

To return it to Metro:

bcdedit /set {current} bootmenupolicy Standard
bcdedit /deletevalue {bootmgr} displaybootmenu

Tips and Tricks

Please add!

Opentegra xorg driver

For the Xfce and MATE desktop environments it is recommended to install the opentegra xorg driver.

https://launchpad.net/~grate-driver/+archive/ubuntu/ppa

Note: do not install Mesa from here! (broken desktop)

Firefox scrolling

Enable Firefox touchscreen scrolling.

Flash kernel

Add a custom config for Surface RT / 2

Create a /boot/efi mount point

Unmount /boot/firmware:

sudo umount /boot/firmware

Delete the now unused folder and create a new /boot/efi folder:

sudo rm -r /boot/firmware
sudo mkdir /boot/efi

Open /etc/fstab:

sudo nano /etc/fstab

Replace this line:

LABEL=system-boot  /boot/firmware  vfat  defaults    0  1

with:

LABEL=system-boot  /boot/efi       vfat  umask=0077  0  1

APX/Fusée Gelée

It is assumed the reader has read the APX Boot page.

Fusée Gelée is run on a amd64/i386 computer. You need the python3-usb package installed. On a 64bit Ubuntu machine you also need the libc6 and libstdc++6 i386 packages (to stop a "no such file or directory" error):

sudo dpkg --add-architecture i386
sudo apt update
sudo apt install python3-usb
sudo apt install libc6:i386
sudo apt install libstdc++6:i386

The openbook wiki refers to (in the commands) a payload file uart_payload_n7.bin which you can download following the links, but the already present payload disable_security_fuses.bin is what is used in the scripts (runuboot.sh etc) in the zip.

Boot script for netboot:

echo 'Linux is booted from boot.scr'

# For rescue mode: setenv bootargs rescue/enable=true ---
setenv bootargs ---

# These should be the defaults already:
#setenv fdt_addr_r=0x83000000
#setenv kernel_addr_r=0x81000000
#setenv ramdisk_addr_r=0x83100000

fatload mmc 1:1 ${fdt_addr_r} tegra30-microsoft-surface-rt.dtb  
fatload mmc 1:1 ${kernel_addr_r} vmlinuz
fatload mmc 1:1 ${ramdisk_addr_r} initrd.gz

# U-boot sets the filesize variable to the size of the last file loaded
bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}

DO NOT use a dtb file for a different machine as this can cause hardware damage!!!

ARM/SurfaceRT (last edited 2022-04-24 18:52:46 by adamsmith)