SurfaceRT

Revision 81 as of 2021-12-21 23:46:05

Clear message

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.

Surface Models

Many Surface 2 owners are unaware they have a Surface 2 because both machines are labelled as 'Surface 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).

  • 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 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.

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 install the leaked Windows 10 via the media builder.

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.

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

The latest kernel binaries can be found here.

UEFI Booting

Surface RT

The Surface RT can use GRUB 2 or UEFI shell as a bootloader. 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. Pre-built bootloader binaries are available.

Unfortunately a bug with the Surface RT's UEFI implementation stops the display from working with most 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].

Surface 2

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 .

You may already have the necessary golden key 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 console=tty0 cpuidle.off=1 initrd=initrd-with-wifi.gz

The Surface 2 will happily boot from a usb drive, but currently looses usb power once the kernel starts. You can get around this if you have a usb hub that provides back power. The SD card slot is configured to act as a serial console so it is probably wise to not have an SD card in there just in case. The emmc, touchcover 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 desktop with its fbturbo driver seems to always work.

Ubuntu Server

Write the image to a USB drive. Copy the appropriate kernel zImage and dtb to the first (called "system-boot") partition on the USB drive. For the Surface RT add a UEFI bootloader (/efi/boot/bootarm.efi) to the same partition.

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 default Raspberry Pi cmdline.txt uses net.ifnames=0 so add that to the surface kernel command line (list of kernel parameters). For example, with the Surface RT your startup.nsh may look like this:

fs0:
zImage dtb=tegra30-microsoft-surface-rt-efi.dtb root=LABEL=writable console=tty1 cpuidle.off=1 net.ifnames=0 rootwait initrd=initrd.img

# shutdown if something went wrong
reset -s

The server image requires a working network on first boot, so you have to 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"

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 and use a GPT partition table if clearing the disk.

Dual 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.

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.

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.

A sample grub.cfg is below (Ubuntu on microdSD card):

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 console=tty0 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 searches for a filesystem with the label "SYSTEM" (which is the efi partition on the Surface RT) and sets root to that partition. 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:

set root=(hd0,2)

You must set the root before the chainloader command.

Change the boot order - https://askubuntu.com/questions/485261/change-boot-order-using-efibootmgr , https://stackoverflow.com/questions/31291158/adding-uefi-firmware-boot-entry-using-bcdedit and http://www.mistyprojects.co.uk/documents/BCDEdit/files/examples4.htm#fwbootmgr -> yet to be tested.

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.

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 test.efi, boot.efi and any other needed files to the boot partition. For example, to copy test.efi from a usb drive:

copy f:\test.efi b: 

Once you are finished remove the drive letter mapping:

mountvol b: /d

Now use bcdedit 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

Possibly useful for the Surface 2 as this should have working touch/type cover...

From an 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

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

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!!!