User Tools

Site Tools



What is here?

Some notes regarding running Linux on the Nintendo Switch. First things first, thanks fail0verflow. I did just play a bit on the software side, but fail0verflow was one of the 2 groups who found the way to run Linux, and established all the chain to make this possible, including providing the patched Linux kernel. You guys rock!


What works (not)?

As of now, you always need to boot into RCM, and then provide a payload to be booted. You then need to provide a payload via USB connection, for example from Android (via NXLoader or a Linux box via Fusee launcher. Hekate is one possible first payload to provide, it can run further software which can be provided on a fat32 formated microsd card.

Runnable software could be one of the Linux distros below, or Lakka/switch (a platform to run emulators), or L4T Ubuntu. These two provide most features, for example audio support via the switch speakers. If you are unsure what to run first, Lakka is a good bet. It can also run sshd, you can connect to wlan and look around.

distro wlan xorg plainxorg acceleratedaudio
Fedora28/29yes yes yesno
Arch Linux/KDE rootfsyesyesyesno
Ubuntu 18.04yes yes yesno
Fedora27 yes yes no no
Debian sid yes yes no no
opensuse Tumbleweedyes yes no no
Lakka/switch yes yes yes yes (via TV)
L4T ubuntu yes yes yes yes

Note: I am seeing crashes under high load. Building the mesa package, rpmbuild parallelizes for the 4 cores and one sees load ~4. After some time, the switch gets hot and turns off. Using this now in the specfile:

make_build MKDEP=/bin/true V=1 -j2

Note: As of today, the switch can not run Linux standalone. You need to shorten 2 pins (i.e. with a hardware device) and supply code to execute via USB using the RCM protocol. Note: There have been reports of hardware being sold, where the payload via USB can no longer be supplied after firmware update here are details.


First steps

At first, one should get preconfigured images from others to run. I followed on a Fedora28 x86_64 host. Issue: Booting was not completing, message “Timeout waiting for hardware interrupt” was displayed. As hinted at , I had to revert patch and recompile the kernel, so my microsd-card got recognized. Wlan just works after a restart.

Installing Fedora

Installing Fedora for the switch on the microsd card, using a Fedora28 x86_64 as host. I created DOS style partitions on a 32GB card, and switch between the partitions in modifying the kernel command line.

For installing Fedora 28, images for several spins are available:

  • Fedora-Server-28-1.1.aarch64: unzipped 7.5GB, if using this you need to install packages NetworkManager-wifi and wpa_supplicant before wlan becomes usable.
  • Fedora-Workstation-28-1.1.aarch64: unzipped 10.7GB, quite fat, including many things I will not need.
  • Fedora-Minimal-28-1.1.aarch64: unzipped 5.4GB, seems like the best choice.
### preparing the new partition
mkfs.ext4 /dev/mmcblk0p4
mount /dev/mmcblk0p4 /mnt/tmp4

### deploying the image
xz -d Fedora-Minimal-28-1.1.aarch64.raw.xz
losetup -f Fedora-Workstation-28-1.1.aarch64.raw 
kpartx -av /dev/loop0 
mount /dev/mapper/loop0p5 /mnt/tmp
cd /mnt/tmp4
tar cfp - *|pv|(cd /mnt/tmp/4 && tar xfp -)

### preparations
vi /etc/fstab
# only need this: /dev/mmcblk0p4 / ext4 defaults 0 0

cd /mnt/tmp4
ln -s /etc/rc.local etc/rc.d/rc.local

# Remember that wlan just works after a soft reboot of Linux.
# As we can not type in 'reboot', we modify /etc/rc.local so
# it does a reboot for us.  Use the following code in /etc/rc.local:

[ -f /etc/flagfile ] || {
        echo "/etc/flagfile does not exist apparently, touching it and rebooting in 10sec"
        touch /etc/flagfile
        dmesg >/var/log/dmesg1
        sleep 10

echo "not rebooting.. and removing flagfile."
rm /etc/flagfile

chmod +x etc/rc.local

# set a root password, for example one from your /etc/shadow
vi etc/shadow

# disable console on tty1.  We have no input anyway, and can
# see debugmessages that way.
mv etc/systemd/system/ root/

### prepare wlan
# copy wlan config file from an existing system
cp mynetwork etc/NetworkManager/system-connections/mynetwork
# required?  I created this while debugging nonworking network.
vi /etc/sysconfig/network-scripts/ifcfg-wlp1s0

# If you installed the Fedora server spin, fetch packages
# wpa_supplicant and NetworkManager-wifi and deploy them into 
# your image.  Either chrooting from a running aarch64 system,
# or using 
# rpm2cpio /tmp/wpa_supplicant-*.aarch64.rpm | \
#    cpio --extract --verbose --make-directories --preserve

# Now we can boot the system.  After the reboot, wlan should
# work.  Login via ssh into root, run dnf upgrade, and install
# the 2 packages cleanly so dnf is aware of them.
dnf update
dnf install NetworkManager-wifi langpacks-ja

systemctl disable auditd
systemctl disable smartd
systemctl disable pcscd

# if you want rpmfusion
dnf install \$(rpm -E %fedora).noarch.rpm \$(rpm -E %fedora).noarch.rpm

Fedora Xorg

ssh root@switch

dnf groupinstall Basic\ Desktop
dnf groupinstall 'LXDE Desktop'

# we will need a virtual keyboard.  This one is simple and small,
# florence is a further option.
dnf install xvkbd

# then, X can be started manually

Fedora Xorg 3D support

At this point, X can be started, but has no 3D support. Fedora 28 and Fedora 29 (rawhide) do not have Tegra support in libdrm and mesa, lets rebuild it.

echo '%_topdir /root/rpmbuild' >~/.rpmmacros

dnf install rpm-build yum-utils rpmdevtools

cd ~/rpmbuild
yumdownloader --source libdrm
rpm -ivh libdrm-2.4.92*fc28.src.rpm
cp SPECS/libdrm.spec SPECS/
vi SPECS/libdrm.spec
# We are changing the release, so the Fedora version
# is not getting reinstalled.
# change 'Release:        1%{?dist}' into 'Release:        1.tegra%{?dist}'

# dependencies
dnf install -y docbook-style-xsl gcc kernel-headers \
  libatomic_ops-devel meson valgrind-devel
rpmbuild -ba --with tegra SPECS/libdrm.spec
# pay attention to:
# Message:   Tegra API      true

# Then install the rebuild package.
rpm -Fvh RPMS/aarch64/*2.4.92*
rpm -ql libdrm|grep tegra

# Now, Fedora28 has only mesa-18.0.1, but we need the current
# pre-18.2 version for tegra support.
# rawhide has mesa-18.1.0-rc3, rebuilding that might work,
# that version has tegra support:
# Instead, I used the specfile from rawhides mesa-18.1.0-rc3,
# and compiled the current git version of mesa-18.2-pre.

# Install build dependencies of the mesa-18.0.1 Fed28 package
dnf install -y autoconf automake bison clang-devel \
  elfutils-libelf-devel expat-devel flex gcc-c++ libXdamage-devel \
  libXext-devel libXfixes-devel libXi-devel libXmu-devel \
  libXxf86vm-devel libclc-devel libomxil-bellagio-devel \
  libselinux-devel libtool libudev-devel libva-devel \
  libvdpau-devel libxshmfence-devel llvm-devel makedepend \
  opencl-filesystem python2-libxml2 python2-mako python3-mako \
  xorg-x11-proto-devel libglvnd-devel wayland-protocols

### The custom Ubuntu packages use these options:
# ./configure --prefix=/usr/ --without-dri-drivers \
#  --disable-gallium-llvm --with-gallium-drivers=nouveau,tegra \
#  --enable-gbm --enable-egl --with-egl-platforms=drm,x11 \
#  --enable-gles1 --enable-gles2 --enable-opengl --enable-osmesa \
#  --enable-shared-glapi --enable-dri3 --enable-glx --enable-glx-tls \
#  --enable-texture-float

rpm -ivh mesa-18.1.0-0.2.rc3.fc29.src.rpm
cd /root/rpmbuild
git clone git://
mv mesa mesa-18.2.0-git02c7916298
tar cf mesa-18.2.0-git02c7916298.tar mesa-18.2.0-rc
mv mesa-18.2.0-git02c7916298.tar SOURCES
mv SPECS/mesa.spec SPECS/

rpmbuild -bb mesa-18.2.0-git02c7916298.spec
cd ../RPMS/aarch64/
rpm -Fvh mesa*18.2.0*

# Then start X, and try somesoftware:

graphical demos/games

  • 'dnf -y install glmark2 extremetuxracer' is a good start
  • 'dnf install freedoom2' also runs nicely: 'prboom -window -iwad <wadfile>'. Explicit OpenGL rendering with '-vidmode gl'.
  • GZDoom can be compiled, but can not be started for me. Neither current, nor older 3.x version. Version 2.x can not be compiled.
  • Amiga emulator : packages just build for x86_64. Rebuilding fails, need to try to build directly.


This is bootstrapped from an installed Fedora27.

dnf -y install debootstrap
mkfs.ext4 /dev/mmcblk0p3
mount /dev/mmcblk0p3 /mnt/mmcblk0p3

debootstrap sid /mnt/mmcblk0p3/
cd /mnt/mmcblk0p3/
echo "proc sid-root/proc proc defaults 0 0" >> etc/fstab 
echo "sysfs /sys sysfs defaults 0 0" >> etc/fstab
echo "/dev/mmcblk0p3 / ext4 defaults 0 0" >> etc/fstab
mount proc proc/ -t proc
mount sysfs sys -t sysfs
cp /etc/hosts etc/
cp /etc/hostname etc/
export LC_ALL=en_US.utf8
chroot . /bin/bash

# now in the debian filesystem
apt-get update
# if it fails, mktemp might be missing, can be copied in from host
cp /usr/bin/mktemp /mnt/mmcblk0p3/usr/bin/

mount -t devpts devpts /dev/pts
echo 'deb sid main contrib non-free' \
echo 'export PATH=/bin:/sbin:$PATH' >>/root/.bashrc
echo 'alias ll="ls -al"' >>/root/.bashrc

apt-get install locales locales-all
apt-get install openssh-server linux-image-arm64 binutils
apt-get install wpasupplicant network-manager
cp /etc/NetworkManager/system-connections/mynet \

# now set a password
# pubkeys should be same as for host
cp -r /root/.ssh/mnt/mmcblk0p3/root/

# modify your switch linux loader, so partition 3 gets started:
# grep mmcblk0p ./shofel2/usb_loader/switch.scr
setenv bootargs 'root=/dev/mmcblk0p3 rw fbcon=rotate:3 rootwait'

ping switch
# login, and do a first functionality test
ssh root@switch
apt-get update; apt-get install bb

Debian Xorg

apt-get install lxde fonts-ipafont-mincho fonts-ipafont-gothic \
  fonts-nanum xfsprogs mesa-utils xfonts-100dpi xfonts-75dpi \
  xfonts-scalable xinput xinit
# now we can bring up X

apt-get install firefox fonts-stix fonts-lmodern xvkbd

Debian compiling dri/mesa

apt-get install git autoconf xutils-dev wget
apt-get install libtool make flex bison build-essential
apt-get build-dep libdrm mesa

git clone git://
cd drm
./configure --enable-tegra-experimental-api --prefix=/usr
make install
cd ..

git clone git://
cd mesa
./configure --prefix=/usr/ --without-dri-drivers \
  --disable-gallium-llvm --with-gallium-drivers=nouveau,tegra \
  --enable-gbm --enable-egl --with-egl-platforms=drm,x11 \
  --enable-gles1 --enable-gles2 --enable-opengl --enable-osmesa \
  --enable-shared-glapi --enable-dri3 --enable-glx --enable-glx-tls \

openSUSE Tumbleweed

# suse has by default no symlink to in /etc/systemd/system .
# It runs the graphical target by default, you need to create the
# link for the plain multiuser target
ln -s /usr/lib/systemd/system/ \
# We also need to setup rc-local compat
ln -s /usr/lib/systemd/system/rc-local.service \
# Also, no /etc/rc.local, but:
mv /etc/rc.local /etc/init.d/boot.init
# We can use the same rc.local/boot.init code as for Fedora.

# By default, Suse tries to start wicked and NetworkManager.
# So if you copy your wlan file to 
# /etc/NetworkManager/system-connections/ , you are fine.

# then, start the image, login and..

hostnamectl set-hostname switch.local
zypper update
zypper install xvkbd qsynergy rss-glx

# X can be started, but pointer detection and screen are not aligned.
# Be sure to _not_ use kernel option fbcon=rotate:X to have them aligned.

rpm -ql rss-glx|grep bin
# these screensavers are usable for me

generic xorg hints

touchscreen detection not in sync

The touchscreen driver will work in horizontal mode by default, but the xorg screen might come up in vertical mode. You can use one of the following 2 things to fix:

  • Modify the touchscreen config to vertical:
cat <<EOT >/etc/udev/rules.d/01-nintendo-switch-libinput-matrix.rules
ATTRS{name}=="stmfts", ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1"
  • or rotate the screen to vertical. For example on lxde, this can be used:
mkdir -p ~/.config/autostart
cat <<EOT >~/.config/autostart/.desktop 
[Desktop Entry] 
Exec=xrandr --output DSI-1 --rotate left

missing tegra driver

gbm: Last dlopen error: /usr/lib/dri/ 
cannot open shared object file: No such file or directory
failed to load driver: tegra
EGL_MESA_drm_image required.

Compile libdrm and mesa with tegra support.

Noteworthy games

The switch is a nice platform for portable gaming, and has many indie game titles. Unfortunately, many are not available in all regions. (-J) means: not available when Japan is set as region in the nintendo store.

  • Thimbleweed park (-J)
  • Into the breach (-J)
  • steamworld dig 2 / スチームワールドディグ2 (+J)
  • The messenger / jump'n'run (+J)
  • Celeste / jump'n'run (+J)
  • Baba is you (-J)
  • Axiom Verge / jump'n'run (+J)
  • Dead cells / jump'n'run (+J)
  • Enter the Gungeon (+J)
hardwarerelated/nintendo_switch.txt · Last modified: 2019/05/18 13:43 by chris