===== What is here? ===== Some notes regarding running Linux on the Nintendo Switch. First things first, thanks [[https://github.com/fail0verflow/shofel2|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. After the initial release, most contributions/enhancements come from the [[https://twitter.com/switchroot_org|switchroot project]]. You guys rock! {{https://fluxcoil.net/files/tmp/20190707_124709_nintendo_switchc.jpg?600x400 }} ===== Links ===== * https://ismyswitchpatched.com/ -- find out if your switch is patched, or if you can install Linux! * https://www.reddit.com/r/SwitchHaxing/ -- reddit switch news * [[https://media.ccc.de/v/c4.openchaos.2018.06.glitching-the-switch|Presentation "glitching the switch" from Andreas Galauner]] * [[software/switch/fedora|My older linux@switch notes]] * [[software/switch/debian|Notes on Debian@switch]] * [[https://www.youtube.com/watch?v=tmGImw8cs0o|Cuda on switch?]] * Darkglider/bell07 [[https://gitlab.com/bell07/gentoo-switch_overlay|Gentoo switch overlays]] * [[/hardwarerelated/raspberry_pi_4#benchmark_results|CPU/memory performance of Raspberry pi 4, Nintendo switch and a Thinkpad L480]] ===== Nintendo Switch Hardware Specs ===== * 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. [[https://www.eurogamer.net/articles/digitalfoundry-2019-switch-new-tegra-x1-silicon-comes-into-focus|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 ===== 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: {{ https://fluxcoil.net/files/tmp/20190616_184612_switch2s.jpg?500x}} * Use chromium (dnf -y install chromium) to run WebGL code: * https://phoboslab.org/wipeout/ * https://media.tojicode.com/q3bsp/ -- quake3 * https://madebyevan.com/webgl-water/ * '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, [[https://gbatemp.net/threads/tutorial-compiling-and-installing-moonlight-embedded-on-l4t-ubuntu.537429/#post-8619150|details]] * running emulators: * reicast: dreamcast emulator * ishiiruka: sega emulator * dolphin: gamecube/wii emulator * citra: 3DS emulator * Karaoke applications like [[https://usdx.eu/|UltraStar Deluxe]] ===== What Linux flavour works (not)? ===== ^distro ^wlan ^xorg plain^xorg accelerated^audio^cuda^ |[[https://www.lakka.tv/doc/Nintendo-Switch/|Lakka (retro game focused)]] |yes | yes | yes | yes | no | |[[https://gbatemp.net/threads/l4t-ubuntu-a-fully-featured-linux-on-your-switch.537301/|L4T Ubuntu]] |yes | yes | yes | yes| yes| |[[/hardwarerelated/nintendo_switch#installing_fedora_32|Fedora 28/29/30/31/32]]|yes | yes | yes| yes | no | |[[https://forum.xda-developers.com/nintendo-switch/nintendo-switch-news-guides-discussion--development/rom-switchroot-lineageos-15-1-t3951389|Android 8.1/LineageOS 15.1]] |yes | n/a | n/a | yes | no | * 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 Fedora32, details are here in the wiki. * **Note:** Newer Nintendo switch can not be brought into RCM, so unsigned payloads via USB can no longer be supplied, this prevents running own code like Linux on these models. ===== Boot order for Linux@switch ===== - 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 [[https://github.com/fail0verflow/shofel2/tree/master/rcm-jig|RCM jig device]]. You can create a Jig yourself, or buy them online. When booting to RCM succeeded, you can use Hekate to set 'autorcm', the switch will then after resets automatically enter RCM instead of booting Nintendos Horizon. - 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 a Linux box via [[https://github.com/Qyriad/fusee-launcher|Fusee launcher]]. - What to run as first level payload? * [[https://github.com/CTCaer/hekate/releases|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 * [[https://github.com/fail0verflow/shofel2|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. * [[https://github.com/Guillem96/argon-nx|ArgonNX]] has more eyecandy than hekate. * [[https://wiki.gbatemp.net/wiki/List_of_Switch_payloads|This is a list of various payloads]] - 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. - 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. ===== L4T Ubuntu 3.2 installation ===== This is also the first step for installing Fedora, L4T will be used to bootstrap. The L4T instructions, for reference, are [[https://gbatemp.net/threads/l4t-ubuntu-a-fully-featured-linux-on-your-switch.537301/|here]]. My notes for installing L4T version 3.0 are now [[/software/switch/l4t-3.0-installation|here]]. * **Requirements:** * A Nintendo switch which is old enough, switch lite and newer normal switches do not boot into RCM. * A microsd-card, 16+ GB * A Linux system with usb3 (Fedora31/x86_64 here) * A USB-C cable, to connect the switch to the Linux system * **Software preparations:** * Download switchroot-ubuntu-3.2.0-2020-10-05.7z from [[https://gbatemp.net/threads/l4t-ubuntu-a-fully-featured-linux-on-your-switch.537301/|here]] * Download hekate_ctcaer_5.5.7_Nyx_1.0.4.zip from [[https://github.com/CTCaer/hekate/releases|here]] * Get fusee-launcher: git clone https://github.com/Qyriad/fusee-launcher # Insert your microsd-card, 32+ GB # Find the microsd-card device, i.e. /dev/mmcblk0p1 parted # create make a single partition, 16GB size. No GPT, partition table. mkfs.vfat /dev/mmcblk0p1 # Now extract hekate, copy contents cd ~/Downloads mkdir hekate_ctcaer_5.5.7_Nyx_1.0.4 && cd hekate_ctcaer_5.5.7_Nyx_1.0.4 unzip ../hekate_ctcaer_5.5.7_Nyx_1.0.4.zip mount /dev/mmcblk0p1 /mnt/tmp tar cf - bootloader|(cd /mnt/tmp && tar xfv -) # now insert the card into the Nintendo switch. * Ensure the switch is turned off * Insert your Jig on the right side * Press the 'volume up' button, keep it pressed * turn on the switch, in pressing the power button. The screen should stay black, so RCM mode. * connect the USB cable to the Linux system * Supply the payload from the Linux system: sudo ./fusee-launcher.py hekate_ctcaer_5.5.7.bin * When hekate is booted, remove the Jig, and activate "auto RCM" in the menu. With this activated, the switch will boot into RCM without the Jig. * enter "Tools", then partition the card. Move the Linux slider to 16GB, then click "next step". When done, remove the card and insert it in the Linux system. # We will extract the archive into the newly created partition mount /dev/mmcblk0p1 /mpt/tmp cd /mnt/tmp 7z x //switchroot-ubuntu-3.2.0-2020-10-05.7z cd ..; umount tmp * Insert the card into the nintendo switch, Hekate should recognize it and reload itself. Enter again Tools/partition manager, then "Flash Linux". The image files we just wrote should be found, flashing to the Linux partition can be started. * Connect the 2 joycons. From the hekate main menu, go to "NYX tools", dump the pairing data. * Remove the microsd card, insert it into the Linux system. # We will extract the update mount /dev/mmcblk0p1 /mpt/tmp cd /mnt/tmp rm -rf bootloader/ini/L4T-bionic.ini switchroot/ubuntu 7z x //switchroot-ubuntu-3.3.0-update_only-2021-04-08.7z cd ..; umount tmp * Move the card to the Nintendo switch again, select "Ubuntu" from "More Configs" * Wait some minutes, work through the setup steps. Select "auto login". * Login: * If you setup WLAN in the first installation steps, you can login via WLAN. * Alternatively, you can login via network over the usb-cable: "modprobe usbnet; ip addr add 192.168.55.2/24 dev enp0s20f0u1; ssh @192.168.55.1". * Use "sudo su -" to become root, and update the installation: "apt update; apt dist-upgrade" ===== Installing Fedora 32 ===== These steps need an already installed L4T on the microsd card: partitions 1 (vfat) and 2 (ext4, L4T) have been set up. After increasing the second partition to 16GB, I create a third partition and install Fedora 32 there. I use a Fedora31/x86_64 system here as helper. For installing the Fedora32 aarch64 userland for the switch, I use Fedora-Server-32_Beta-1.2.aarch64.raw.xz. The images for Fedora31/32 do not come with wpa_supplicant, we need to install it manually. Networkmanager-wifi is part of the images. ### The following steps are done on the Fedora31/x86_64 system, ### with the microsd card with L4T installed. fdisk /dev/mmcblk0 # n / p / 3 / / mkfs.ext4 /dev/mmcblk0p3 mount /dev/mmcblk0p3 /mnt/tmp3 cd /mnt/tmp3 xz -d Fedora-Server-32_Beta-1.2.aarch64.raw.xz kpartx -av Fedora-Server-32_Beta-1.2.aarch64.raw vgscan vgchange -ay mount /dev/fedora/root /mnt/tmp cd /mnt/tmp tar cfp - *|pv|(cd /mnt/tmp3 && tar xf -) # Now, as the copy finished, preparations cd /mnt/tmp3 echo '/dev/mmcblk0p2 / ext4 defaults 0 0' >etc/fstab # set a root password, for example one from your /etc/shadow vi etc/shadow # Now either add your ssh-pubkey to root/.ssh/authorized_keys, # or modify etc/ssh/sshd_config to accept password root logins. 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/ # Our Fedora-server image lacks package wpa_supplicant. # The package has to be fetched, and installed. # Either # - chroot into the Fedora partition, and "rpm -i " # (needs to be done from an aarch64, for example the L4T) # - or use # cd /mnt/tmp2 # rpm2cpio | cpio --extract --verbose --make-directories --preserve # We have 2 options: # a) create an own inifile for Fedora on the boot partition, # then we have full control over kernel parameters, but # we need to write a new boot.scr file # b) Or, we just exchange partitions 2 and 3 in the # partition table. Doing that for now. # twist partitions 2 and 3 with sfdisk sfdisk /dev/mmcblk0 -l >/root/ptable_normal cp /root/ptable_normal /root/ptable_twisted vi /root/ptable_twisted # change mmcblk0p2 -> mmcblk0p3, and # the original mmcblk0p3 -> mmcblk0p2 sfdisk /dev/mmcblk0 --force etc/modules-load.d/brcmfmac.conf cp /mnt/tmp2/lib/firmware/brcm/brcmfmac4356-pcie.txt lib/firmware/brcm/ cp -r /mnt/tmp2/lib/modules/4.9.140+/ lib/modules # 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< /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 :) # - mplayer: media player, blueman: connect bt headsets etc. dnf install -y xvkbd synergy f29-backgrounds-base mplayer blueman # Now copying drivers from an L4T installation on partition2: mount /dev/mmcblk0p3 /mnt/tmp3/ cd /mnt/tmp3 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 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</home/$MYUSER/.config/lxsession/LXDE/autostart<> \ /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< ADMAIF1 # we should now be able to start X, and have sound output: mplayer # 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:** Can I use multiple partitions on one sdcard? * **A:** Yes. You can setup L4T as per instructions, and enlarge the L4T partition, for example to 16GB. You can create further partitions after that area, and later twist the partitions to select what to boot. Alternatively, you could create own boot-inis to easily select which Linux to start from hekate. * **Q:** Can I compile kernels on Fedora? * **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 ? * **Q:** Something is not working.. * **A:** You might want to have a look at the [[https://github.com/gamingnation1/l4t-fedora|L4T-Fedora]] repo, verify the configfiles and deployment with the one from here. ===== RHEL8/aarch64 ===== * RHEL8 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. EPEL8 might have further window managers. # 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 <~/.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_fed.svg` * Open in firefox: `firefox systemd_plot_fed.svg` === 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: * https://www.kernel.org/doc/html/v4.16/driver-api/usb/usb3-debug-port.html#serial-tty * https://stackoverflow.com/questions/45511533/can-i-get-debug-information-on-usb * files initrd: /lib/firmware/tegra21x_xusb_firmware /lib/firmware/tegra210b01_xusb_firmware === 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.conf section: screens dennou.local: switch.local: end section: links dennou.local: up = switch.local switch.local: down = dennou.local end [chris@電脳 ~]$ synergys [chris@電脳 ~]$ === 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 saw ext4 corruptions on a 32GB card, 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