User Tools

Site Tools


Sidebar

hardwarerelated:nintendo_switch

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!

20190707_124709_nintendo_switchc.jpg

hardware

  • cpu:
    • Nvidia Tegra X1, model T210: 4x Cortex-A57, 4x Cortex-A53 (big.LITTLE approach, but Linux kernel 4.16 is just presenting the 4 A57 cores)
    • note: several variants of the switch are around, newer ones do not allow to run unsigned code from the RCM. The serial number can be used to check this. Cpu variant details
    • Nvidia Maxwell GPU
    • 4GB LPDDR4 RAM
  • wlan:
    • chip: broadcom 4356
    • driver: brcmfmac
  • audio
    • chip: ALC5639
  • power
    • 'upower -d' hands out good data, also 'acpi'
    • charging from linux works

Todo

The Fedora30/switch build does most of what I need now. Just these things might be interesting to look into:

  • 3D is not running properly in all details: supertuxkart do not run, and firefox plays no webgl. Investigation details.
  • Research CUDA support. Would be awesome to utilize the tegra cores for image manipulation. Is CUDA here pure graphic, or AI style computing? The switch might be a nice platform for playing with AI code then! The switch Tegra has double the power of the Nvidia Jetson nano board. link1 link2 link3

Graphical demos/games

What are people actually using the Nintendo switch/Linux setups for? Some use it like a workstation on HDMI output, with the option of undocking and using it on the road. Of course, databases, libreoffice and so on work. Some more graphical ideas to try out:

20190616_184612_switch2s.jpg

  • Use chromium (dnf -y install chromium) to run WebGL code:
  • 'dnf -y install glmark2 extremetuxracer'
  • 'dnf install freedoom2' also runs nicely: 'prboom -window -iwad /usr/share/doom/freedoom.wad'. Explicit OpenGL rendering with '-vidmode gl'.
  • mplayer can play videos fetched with youtube-dl
  • Recompile bb, with the patches from debian. I did not get it compiled with libmikmod though, so no sound: https://packages.debian.org/sid/bb
  • Scummvm with 'Secret of Monkey Island'
  • Amiga emulator https://fs-uae.net/ : packages just build for x86_64. Rebuilding fails, need to try to build directly.
  • moonlight: streaming windows games to the switch, details
  • running emulators:
    • reicast: dreamcast emulator
    • ishiiruka: sega emulator
    • dolphin: gamecube/wii emulator
    • citra: 3DS emulator
  • Karaoke applications like UltraStar Deluxe

What works (not)?

  • For a start, setting up Lakka/switch (a distro intended to run emulators) or the L4T Ubuntu is best for most people. These provide most features, for example audio support via the switch speakers. They can also run sshd, you can connect to wlan and look around.
  • With more work you can also bootstrap Fedora30, details are here in the wiki. I have not published complete images for Fedora30.
distro wlan xorg plainxorg acceleratedaudio
Lakka/switch yes yes yes yes
L4T ubuntu yes yes yes yes
Fedora28/29/30yes yes yes yes
Arch Linux imageyesyesyesno
Ubuntu 18.04yes yes yesno
Debian sid yes yes no no
openSUSE Tumbleweedyes yes no no

Note: There have been reports of hardware being sold after July 2018, where unsigned payloads via USB can no longer be supplied, this prevents running own code like Linux on these models.

Boot order for Linux@switch

  1. As first step, the switch needs to be booted into RCM, an early debug mode. For doing this for the first time, pins on the switch need to be crossed, for example using this RCM jig device. When this succeeded one time, you can use Hekate to set 'autorcm', the switch will then after resets always enter RCM instead of booting Nintendos Horizon.
  2. With the switch being in RCM, it will do nothing, the screen will be black. At this state, payload code to be run needs to be supplied via USB. The code can be supplied from Android (via NXLoader) or a Linux box via Fusee launcher.
  3. What to run as first level payload?
    • Hekate could be used, offered via Fusee launcher. Hekate can then
      • configure 'autorcm'
      • it can verify the switches battery charge state
      • it can run Linux kernels from microsd-cards in the switch (using coreboot)
      • it can poweroff the switch
    • Shovel2 can be used to upload Linux kernels via USB, coreboot is also here used. Userland to be booted could be on the microsd card, or supplied via NFS.
    • ArgonNX has more eyecandy than hekate.
  4. Which kernel to run? There are basically 2 levels of kernel patches.
    • mid-2018 kernel, using the initial patches from Fail0verflow: no audio, problems charging the switch, resets when load is high (compile things only with 'make -j1'), wlan only works after one reset of the system. Yet, on this kernel one can see Linux console output directly on the screen after booting. This kernel is great for initially running for example Fedora30, Opensuse or Debian userlands: because you can use the screen to get debugging output, until you get the userland appropriately configured to log into wlan after booting. From that state on you can work via SSH.
    • mid-2019 kernel from the L4T distro with nvidia patches: audio, charging and wlan work, no resets under high load. But no initial console output. Lakka and the L4T distro use this kernel. The Lakka bootchain.
  5. Which userland to run? L4T and Lakka come with kernel/userland together. The kernels with switch patches can be used on other userlands though, like Fedora30, SuSE, Debian.

Fedora boot order

2 variants can be used:

  1. loading kernel/initrd from sdcard
  2. or via USB.

I use USB so far, it's easier to exchange kernels. Single steps (nicely summed up here):

  • Switch booting into to Tegra RCM flashing mode over USB
  • ShofEL2 boots Coreboot
  • Coreboot initializes hardware and launches U-Boot as its payload
  • U-Boot starts SDP flashing mode over USB
  • imx-usb-loader loads Linux kernel, device tree, and U-Boot script via SDP
  • U-Boot script decompresses (if comressed kernel) and boots Linux

Installing Fedora 30

I am installing Fedora for the switch on the microsd card, using a Fedora30 x86_64 as host. I created DOS style partitions on a 32GB card, and switch between the partitions in modifying the kernel command line. First, I installed L4T on the card, this did setup partitions 1 (vfat) and 2 (ext4, L4T). After increasing the second partition to 16GB, I created a third partition and installed Fedora 30 there.

L4T is booting the linux kernel from the card, but I am booting Fedora with kernel/initrd supplied via USB. For this, I have compiled shovel2/coreboot from this guide. I also compiled the kernel as per these instructions, but it has many downsides over the L4T kernel. I am booting Fedora with the L4T kernel. Details on how I boot kernels are here

For installing the Fedora30 aarch64 userland for the switch, I used Fedora-Server-30-1.2.aarch64.raw.xz. Despite being the server spin, it comes with packages wpa_supplicant and Networkmanager-wifi.

### preparing the new partition
mkfs.ext4 /dev/mmcblk0p3
mount /dev/mmcblk0p3 /mnt/tmp3

### deploying the image
xz -d Fedora-Server-30-1.2.aarch64.raw.xz
kpartx -av Fedora-Server-30-1.2.aarch64.raw
vgscan 
vgchange -ay
mount /dev/fedora/root /mnt/tmp
cd /mnt/tmp
tar cfp - *|pv|(cd /mnt/tmp3 && tar xfp -)

### preparations
cd /mnt/tmp3
vi etc/fstab
# only need this: /dev/mmcblk0p3 / ext4 defaults 0 0

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

echo switch.local >etc/hostname
echo '127.0.0.1   switch.local switch' >>etc/hosts

# disable console on tty1.  We have no input anyway, and can
# see debugmessages that way - via HDMI
mv etc/systemd/system/getty.target.wants/getty@tty1.service root/

### prepare wlan
# I have my wlan already setup on my Fedora30 host system,
# so I can simply copy over the files
cp /etc/sysconfig/network-scripts/keys-mynetwork \
   /etc/sysconfig/network-scripts/ifcfg-mynetwork \
    etc/sysconfig/network-scripts/

# Now we can boot the system.  After the reboot, wlan should
# work.  Login via ssh into root, run dnf upgrade,
# remove and install packages
dnf remove iscsi-initiator-utils-iscsiuio iscsi-initiator-utils \
  clevis-luks atmel-firmware
dnf install -y langpacks-ja upower screen
dnf update -y

for i in auditd smartd pcscd ModemManager multipathd mdmonitor \
         dmraid-activation initial-setup lvm2-monitor zram-swap \
         plymouth-start lm_sensors udisks2 ; do
    systemctl disable $i
done

### tuning, seen in the L4T scripts
cat >/etc/rc.local<<EOT
#!/usr/bin/bash
echo 2048 > /sys/block/mmcblk0/queue/read_ahead_kb
echo 0 > "/proc/sys/vm/lazy_vfree_pages"
EOT
chmod +x /etc/rc.local
/etc/rc.local
ln -s /etc/rc.local /etc/rc.d/rc.local

### if you want rpmfusion
dnf install \
  https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \
  https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

Fedora Xorg/LXDM autologin

ssh root@switch

# Install the basic environment.
dnf -y groupinstall 'Basic Desktop' 'LXDE Desktop'

# Install
# - xvkbd, a virtual keyboard.  'florence' is a further option.
# - synergy, so I can use mouse/keyboard of my linux box
# - f29-backgrounds, because they are awesome :)
dnf install -y xvkbd synergy f29-backgrounds-base mplayer

# Now copying drivers from an L4T installation on partition2:
mount /dev/mmcblk0p2 /mnt/tmp2/
cd /mnt/tmp2

cp usr/lib/xorg/modules/drivers/nvidia_drv.so \
  /usr/lib64/xorg/modules/drivers/
cp usr/lib/xorg/modules/extensions/libglxserver_nvidia.so \
  /usr/lib64/xorg/modules/extensions/
cp /mnt/tmp2/usr/bin/dock-hotplug /usr/bin

mkdir -p /usr/lib/aarch64-linux-gnu
cp -r usr/lib/aarch64-linux-gnu/tegra-egl \
  /usr/lib/aarch64-linux-gnu
ln -s /usr/lib/aarch64-linux-gnu/tegra-egl/ld.so.conf \
  /etc/ld.so.conf.d/aarch64-linux-gnu_EGL.conf
cp -r usr/lib/aarch64-linux-gnu/tegra \
  /usr/lib/aarch64-linux-gnu
ln -s /usr/lib/aarch64-linux-gnu/tegra/ld.so.conf \
  /etc/ld.so.conf.d/aarch64-linux-gnu_GL.conf

ldconfig

cp -r lib/firmware/tegra21x lib/firmware/gm20b /lib/firmware/
cp lib/firmware/bcm4354.hcd /lib/firmware/

# special xorg config
cat >/etc/X11/xorg.conf<<EOT
Section "Module"
    Disable     "dri"
    SubSection  "extmod"
        Option  "omit xfree86-dga"
    EndSubSection
EndSection

Section "Device"
    Identifier  "Tegra0"
    Driver      "nvidia"
    # Allow X server to be started even if no display devices are connected.
    Option      "AllowEmptyInitialConfiguration" "true"
    Option      "Rotate" "CW"
EndSection

Section "InputClass"
    Identifier "evdev touchscreen catchall"
    MatchIsTouchscreen "on"
    MatchDevicePath "/dev/input/event*"
    Driver "evdev"
    Option "InvertX" "no"
    Option "InvertY" "no"
    Option "SwapAxes" "no"
    Option "Calibration" "0 1279 0 719"
EndSection

Section "Monitor"
    Identifier "DFP-0"
    Option "Rotate" "left"
EndSection 
EOT

# MYUSER="lxde"
MYUSER="chris"
useradd -m $MYUSER

mkdir -p /home/$MYUSER/.config/lxsession/LXDE
cat >/home/$MYUSER/.config/lxsession/LXDE/autostart<<EOT
@lxpanel --profile LXDE
@pcmanfm --desktop --profile LXDE
@synergy-core --client 192.168.0.3
EOT
chown -R $MYUSER /home/$MYUSER/.config

# configure autologin
vi /etc/lxdm/lxdm.conf
# autologin=username  # <- insert the username which you use
# session=/usr/bin/startlxde

# We need to ensure that our user later appears in the 'who' output.
# That is important for the /usr/bin/dock-hotplug script, for
# switching screens.
echo 'sessreg -a -l $DISPLAY -x /etc/X11/xdm/Xservers $USER &' >> \
  /etc/lxdm/PostLogin
echo 'sessreg -d -l $DISPLAY -x /etc/X11/xdm/Xservers $USER &' >> \
  /etc/lxdm/PostLogout

rm -f /etc/systemd/system/display-manager.service
systemctl enable --now lxdm
systemctl set-default graphical.target

Fedora sound

# Now copying drivers from an L4T installation on partition2.
mount /dev/mmcblk0p2 /mnt/tmp2/
cd /mnt/tmp2

dnf install -y alsa-ucm alsa-plugins-pulseaudio alsa-utils \
  pulseaudio pulseaudio-module-x11 pulseaudio-utils pavucontrol
cp -r usr/share/alsa/ucm/tegra-snd-t210ref-mobile-rt565x/ /usr/share/alsa/ucm/
cp usr/share/alsa/cards/tegra-hda.conf /usr/share/alsa/cards

cp -r opt/nvidia/ /opt/
cp usr/sbin/nv* usr/sbin/brcm* /usr/sbin/
cp -r etc/nv* /etc/
cp etc/systemd/nv* /etc/systemd
cp etc/systemd/system/nv*service /etc/systemd/system/

cp etc/asound.conf.* /etc/

# ensure that /etc/asound.conf is linked to
# the appropriate file, depending on whether we are docked or not
cat >/etc/udev/rules.d/92-dp-switch.rules<<EOT
SUBSYSTEM!="switch", GOTO="dp_end"
KERNEL!="dp", GOTO="dp_end"
ATTRS{state}=="1", TEST=="/proc/asound/tegrahda", RUN+="/bin/ln -sf /etc/asound.conf.tegrahda /etc/asound.conf"
ATTRS{state}=="1", TEST=="/usr/bin/dock-hotplug", RUN+="/usr/bin/dock-hotplug"
ATTRS{state}=="0", TEST=="/usr/bin/dock-hotplug", RUN+="/usr/bin/dock-hotplug"
ATTRS{state}=="0", TEST=="/proc/asound/tegrasndt210ref", RUN+="/bin/ln -sf /etc/asound.conf.tegrasndt210ref /etc/asound.conf"
LABEL="dp_end"
EOT

# reboot

# for playing via alsa, this has to be active:
alsamixer # I2S1 Mux -> ADMAIF1

# we should now be able to start X, and have sound output:
mplayer <something> 

# When the switch is docked, the screen should switch to HDMI
# output automatically, via profile switch in /usr/bin/dock-hotplug .
# The profile can also be selected via 'pavucontrol' from X.

# also for output testing: 
# speaker-test –channels 2 –rate 48000 –device hw:0,3​

Fedora/switch FAQ

  • Q: Can I use XFS?
  • A: Not if you use the kernel as compiled by the L4T project. It has no support for XFS
  • Q: Has Fedora30/switch all features of L4T and Lakka?
  • A: It uses the same kernel, the biggest things like xorg & sound are working. I have not looked into bluetooth, hdmi/sound output, automatic screen switching when docking/undocking.
  • Q: Can I use multiple partitions on one sdcard?
  • A: Yes. You could setup L4T as per instructions, and enlarge the second partition to 16GB. You can create further partitions after that area, and later 'select' which partition to boot from the kernel options handed over when booting the kernel. I am not booting kernels via hekate/vfat partition, but via shovel2/coreboot/usb. With this, I can conveniently on the Linux system running shovel2 select the kernel options.
  • Q: Can I compile kernels on Fedora30?
  • A: I did not succeed to recompile the L4T kernel on Fedora30/switch with the native GCC9. Seems like it does not go well with the tegra-specific patches from nvidia. Maybe with GCC8. Or compile custom kernels on L4T/switch, or crosscompile on Linux/AMD64. As for debugging why a self compiled kernel is not booting: when docked, debug messages can be seen via HDMI output.
  • Q: Why can I not run glxgears?
  • A: Run 'strace -f -o logg glxgears' to see details, might just be a permission issue. Accessing /dev/nvhost-ctrl or /dev/nvmap ?

EL8/aarch64

  • EL8 userland runs ok with the L4T kernel.
  • Do not use XFS, the L4T kernel does not include the xfs driver.
  • Note: EL8 comes with basic xorg, I was able to run an X and xterm, but no gnome. Also EPEL8 is not yet available and once released it's not clear if it will contain further window managers. See EPEL8 planning page
# I used the cloud image as base, mounted and copied
# the contents to the second partition of a microsdcard
guestmount -a /tmp/image.qcow2 -m /dev/sda2 /mnt/tmpimage
mount /dev/mmcblk0p2 /mnt/tmp2/
cd /mnt/tmpimage
tar cfp - *|pv|(cd /mnt/tmp2 && tar xfp -)
guestunmount /mnt

cd /mnt/tmp2
# have to add contents wpa_supplicant and
# NetworkManager-wifi packages
rpm2cpio ..

# move cloudinit
mkdir etc/systemd/system/tmp
mv etc/systemd/system/multi-user.target.wants/cl* etc/systemd/system/tmp
  • For running xorg: the Fedora30 steps for taking over drivers can be used, and 'startx' brings up Xorg. As windowmanagers, these 2 are available as packages:
    • metacity ('exec /usr/bin/metacity' in ~/.xinitrc)
    • matchbox-window-manager ('/usr/bin/matchbox-window-manager in ~/.xinitrc)
  • No virtual keyboard x-application seems to be available. So this, or synergy, would have to be compiled and installed by hand.

Generic 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. Above xorgs monitor definition should rotate the monitor for all Xorg windowmanagers, but the rotation could instead also be done at the windowmanager level. Rotating the screen in LXDE:

mkdir -p ~/.config/autostart
cat <<EOT >~/.config/autostart/.desktop 
[Desktop Entry] 
Type=rotater
Exec=xrandr --output DSI-0 --rotate left
EOT

booting is slow

Use systemd to illustrate what takes time at boot, and consider to disable services. Also comparing the graph from Fedora30 with the one from L4T helps. This helped me tremendously getting boottime down, after turning the switch on, it takes now 29sec until the usable LXDE screen of Fedora30. I supply the kernel via usb instead of reading from disk, that is further potential for optimization, takes 5.2sec until kernel/initrd etc. are transferred and the kernel is booted.

  • Generate graph: `systemd-analyze plot >systemd_plot_fed30.svg`
  • Open in firefox: `firefox systemd_plot_fed30.svg`

synergy L4T

# install synergy
apt-get install quicksynergy
# run this as client
/usr/bin/synergyc -f --name switch.local 192.168.0.3
# run this if the mouse is not visible
gsettings set org.gnome.settings-daemon.plugins.cursor active fa
lse

console debugging

With newer kernels, there is no console output any more. After booting the kernel, this switch screen just flashes up. Possible alternate debugging with console over usb, the L4T initrd has usb-debug libraries:

How to run the synergy server?

You are running the synergy client for mouse/keyboard sharing, in the LXDE autostart. But what to run to get the server part? I use this:

[chris@電脳 ~]$ cat ./synergy-server.sh 
#!/usr/bin/bash
synergy-core --server --name ThinkPadL480 --config /home/chris/synergy.conf
[chris@電脳 ~]$ 
[chris@電脳 ~]$ cat synergy.conf 
section: screens
        ThinkPadL480:
        switch.local:
end

section: links
        ThinkPadL480:
                up = switch.local
        switch.local:
                down = ThinkPadL480
end
[chris@電脳 ~]$ 

L4T cleanup

Steps/reminders after setting up L4T..

ssh-copy-add chris@switch
echo "alias su='sudo su -'">>~/.bashrc
# as root
apt-get update
apt-get remove --purge kde-window-manager kinit kio kpackagetool5 kwayland-data kwin-common kwin-x11
apt-get dist-upgrade
apt-get install pv

microsd card benchmark

Do this in the switch, as the reader is quite good, better than the one in my thinkpad.

pv /dev/mmcblk0 >/dev/null
Toshiba 32GB 100MB/sec : 80MB/sec
LAZOS 32GB             : 65MB/sec

dealing with filesystem corruptions

I use 2 micro-sd cards, 16GB and 32GB. I run L4T and Fedora30/L4T-kernel on the 32GB card, and see ext4 corruptions there, on both partitions. Using the RPM checksums to verify:

for i in $(rpm -qa|sort); do echo "### $i"; rpm -V $i; done  >>logg
egrep -B1 -v '^#|\.uuid' logg2|grep -c '^#'
egrep -B1 -v '^#|\.uuid' logg2|grep '^#'

overclocking

# enable overclocking
echo 1 >/sys/kernel/tegra_cpufreq/overclock
# set maximum frequency
echo 2091000 >/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq
# cet current frequency
cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq 
# set governor
echo performance >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor

microsd card not found

After having the switch not used for some weeks, microsd cards were no longer recognized. Kernels supplied via USB did not find the card/partitions. Also hekate, when booted as payload via usb, did not find any cards - even ones which worked perfectly fine before. Plugging cards in multiple times/taking out/plugging in did apparently clean contacts, and the cards were recognized again.

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 https://thimbleweedpark.com/ (-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)
  • Vectronom (-J)
  • Axiom Verge / jump'n'run (+J)
  • Dead cells / jump'n'run (+J)
  • Enter the Gungeon (+J)
  • Cadence of Hyrule Crypt of the NecroDancer
  • Hollow knight
hardwarerelated/nintendo_switch.txt · Last modified: 2019/08/31 10:50 by chris