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


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

More information on hardware including touch/type covers can be found here.

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.

  • Work continues on an UEFI privilege escalation to disable TrustZone memory protection and consequently gain full control of the hardware. As of February 2023 'the exploit' can load U-boot (and subsequently the linux/Android kernel) on the Surface RT, but is limited to one CPU core.

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. Be warned, now that Windows 8.1 is EOL, the store no longer works and cannot be used to reinstall apps.

Once you have a completely fresh install (or have wiped the eMMC) 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.

The 3.x Surface RT Android based kernels do not use a dtb. With a small modification these can be used with older versions of Ubuntu.

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 (this won't print anything to the screen, please see the dual-booting section below for that):

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

A startup.nsh may look like this:

zImage dtb=tegra30-microsoft-surface-rt-efi.dtb root=/dev/sda2 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 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 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 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
#  eth0:
#    dhcp4: true
#    optional: true
    dhcp4: true
    optional: true
        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/


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)

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.

Nexus 7 (2012 "grouper") image

This could be an interesting image to be used with the Surface RT as they both use the Tegra 3. The old wiki project page gives information about the image with a separate page for the Nexus 7 android kernel.

The image should be booted with a modified Surface RT android kernel.

Extracting the root filesystem from the downloaded nexus image is a somewhat convoluted affair. First you need to unzip it and convert it to a 'proper' img before it can be mounted (this creates a non-sparse 6GB image):

sudo apt install android-sdk-libsparse-utils
gunzip ubuntu-13.04-preinstalled-desktop-armhf+nexus7.img.gz
simg2img ubuntu-13.04-preinstalled-desktop-armhf+nexus7.img nexus-tmp.img
mkdir img-mnt
sudo mount -o loop nexus-tmp.img img-mnt

Format a partition on the SD card as ext4 (replacing /dev/partition as necessary, e.g. /dev/sdX2 or /dev/mmcblkXp2):

sudo mkfs.ext4 -O ^metadata_csum,^64bit /dev/partition

To make this usable with the android kernel it needs to be 32 bit and have the metadata_csum removed. This can also be achieved with tune2fs and resize2fs. In the example below the journal is also removed:

sudo e2fsck -f /dev/partition
sudo resize2fs -s /dev/partition
sudo tune2fs -O ^metadata_csum /dev/partition
sudo tune2fs -O ^has_journal /dev/partition

Mount the partition and extract the root filesystem:

mkdir raring-mnt
sudo mount /dev/partition raring-mnt
sudo tar --same-owner --numeric-owner -pxf img-mnt/rootfs.tar.gz -C raring-mnt

Be careful with the above command as you don't want to override your working linux system!

Once thats done:

sudo umount img-mnt
rm nexus-tmp.img

To make ubiquity (the installer) start on first boot:

sudo touch raring-mnt/var/lib/oem-config/run

Create an fstab:

echo "none       /proc  proc    nodev,noexec,nosuid     0       0"  | sudo tee raring-mnt/etc/fstab
echo "/dev/mmcblk1p2    /       ext4    defaults,noatime,nodiratime             0       1"  | sudo tee -a raring-mnt/etc/fstab

Let flash-kernel know about the Surface RT (this is a bit hacky and likely to break on update):

echo $'\n'Machine: surface-rt | sudo tee -a raring-mnt/usr/share/flash-kernel/db/all.db
echo Method: nothing | sudo tee -a raring-mnt/usr/share/flash-kernel/db/all.db

Finally, unmount:

sudo umount raring-mnt

We don't need the companion Nexus bootimg, but for those curious it can be downloaded and then extracted with:

mkdir bootimg
cd bootimg
sudo apt install abootimg
abootimg -x ../ubuntu-13.04-preinstalled-desktop-armhf+nexus7.bootimg

The resulting initrd.img can be further unpacked with the usual tools. Within this you'll find the ac100-tarball-installer script that automatically extracts the root tarball, populates fstab and changes the kernel command line for the installed system. Essentially what we have done above.

Random links that can be trawled for more info are: (looks like 'saucy' was the last)

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


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/working display 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

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
        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" {
menuentry "System restart" {
        echo "System rebooting..."
menuentry "System shutdown" {
        echo "System shutting down..."

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 eMMC's efi boot partition. For example, to copy the files from drive f:

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

If your linux filesystem is on the eMMC/USB then the zImage, dtb and initrd doesn't have to be placed on the efi boot partition, but you may wish to put them there for simplicity. If your linux root filesystem is on a microSD card then you will have to copy those files too.

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


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.

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


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

APX/Fusée Gelée

APX (perhaps more correctly called USB Recovery Mode "RCM") is starting the Surface RT with the help of another computer linked with a USB cable. As always further info can be found on the Open Surface RT wiki.

Fusée Gelée is run on a amd64/i386 linux (or WSL) computer with a USB3 port. On this 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 necessary pre-built Fusée Gelée binaries can be downloaded from here. To these you will need to add U-Boot compiled for the Surface RT. Follow the instructions in the included "".

Connect the Surface RT to the USB3 port of the other computer. Enter APX mode by pressing the Surface RT's power button with the volume up button also pressed. The screen will remain blank. Running "dmesg" on the connected computer you should see:

[  423.764974] usb 1-1: new high-speed USB device number 7 using xhci_hcd
[  423.913876] usb 1-1: New USB device found, idVendor=0955, idProduct=7130, bcdDevice= 1.03
[  423.913885] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  423.913890] usb 1-1: Product: APX
[  423.913895] usb 1-1: Manufacturer: NVIDIA Corp.

For one time only extract the BCT (this can be skipped on subsequent boots):

cd surfaceRT_FuseeGeleeTools
sudo ./

At the end of the long output you should see:

 retrieving bct into: ./bct/surface_rt_bct.BIN
./bct/surface_rt_bct.BIN received successfully

Force the Surface RT to power off by holding the power button down for 10 seconds.

Enter APX mode again, but this time runUboot:

sudo ./

If all went well you should now see something on the Surface RT display.

Note: The Open Surface RT wiki refers to (in the commands) a payload file "uart_payload_n7.bin" which you can download following the links, but the scripts in the zip ( etc) use the already included payload "disable_security_fuses.bin".

The latest (2023) versions of U-Boot expect to read a configuration file uboot.env placed on the USB/microSD/eMMC, but if you want to go old school, then here is the 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 2023-03-15 13:00:00 by adamsmith)