Notes on Linux 5.16 RC1 Deployment for Apple M1 Mac Mini

What works / doesn’t work?

  • 10G Ethernet: Untested. 1G connectivity works for sure.
  • WiFi: Can’t find wireless card.
  • Audio: Neither HDMI nor onboard audio works.
  • USB Audio: Works. If you use Apple USB-C to 3.5mm dongle, connect your headphones / speakers to the dongle first before plugging the dongle into Mac Mini.
  • USB3: Degraded speed on type C ports – Operates at 300Mbit/s. Type A ports are fully functional.
  • Graphics: fbcon / kmscon works without issue. Can start GUI with llvmpipe and is in fact fast enough to run gnome.
  • Built-in NVME drive: Block device nodes exist. My system is not deployed on the internal SSD. Actual usuability and performance remain untested.

Devices and Software

  • A linux host where you build the kernel and the bootloader.
  • A M1 Mac Mini. Mine has 10Gbit ethernet.
  • A USB drive to serve as a makeshift root device.
  • A USB-something to USB-C 3.0 cable for sideloading kernel and initrd.
  • A USB keyboard hooked on the Mac Mini.

Compiling

Build the kernel first. Make sure environment variable is set:

  • ARCH=arm64
  • CROSS_COMPILE= the path of the cross compiler tool chain.
  • INSTALL_MOD_PATH= /usr in the thumbdrive root file system.

Verify you have arch/arm64/boot/Image.gz, arch/arm64/boot/dts/apple/t8103-j274.dtb. Run make modules_install and make sure the kernel modules are correctly stored at <thumbdrive>/usr/lib/modules/<version-localversion>.

There’s no good way to generate an initrd without messing around with QEMU userspace emulation or going to another arm64 Linux machine. Since we are already in a chroot, you may configure root passwords, hostname / timezone and other stuff in there as well. See a random Stack Exchange post on how to do this.

Building m1n1 is very straight forward. Modify the first line in Makefile and set ARCH to ${CROSS_COMPILE}, then follow README at https://github.com/AsahiLinux/m1n1. Find compiled m1n1.macho in build/.

Follow AsahiLinux Dev Quick Start to provision disk space from Mac OS, transfer m1n1.macho to 1TR and use kmutil to use m1n1 as a custom boot object, connect Mac Mini to build host with a USB cable.

Sideloading Kernel and Initrd

m1n1 has a bunch of python scripts to interact with a Mac running m1n1. When the Mac mini is connected to the Linux PC it should appear as a USB serial device, something like /dev/ttyACM0.

Set environment variable M1N1DEVICE to /dev/ttyACM0. Invoke proxyclient/tools/linux.py to sideload a kernel like this:

python3 linux.py \
    -b 'root=/dev/sda1 rw earlycon console=tty0' \
    ${kernel_source}/arch/arm64/boot/Image.gz \
    ${kernel_source}/arch/arm64/boot/dts/apple/t8103-j274.dtb \
    /path/to/initramfs-5.16.0-rc1-cth-m1+.img

Bootable m1n1 + Kernel Payload

Use the following command to concatenate m1n1 and other stuff used to boot:

cat m1n1.macho \
    <(echo 'boot-args=root=/dev/sda1 rw earlycon console=tty0') \
    ${kernel_source}/arch/arm64/boot/Image.gz \
    ${kernel_source}/arch/arm64/boot/dts/apple/t8103-j274.dtb \
    /path/to/initramfs-5.16.0-rc1-cth-m1+.img \
> /tmp/m1n1+kernel.macho

The combined boot object can be used to boot directly into Linux without another PC.

Notes

Booting from iSCSI

At boot pass parameters root=UUID=XXXX ip=dhcp rd.iscsi.initiator=iqn.<host-iqn:identifier> netroot=iscsi:<server-ip>::::iqn.<server-iqn:target> instead of a normal root=/dev/XXX. Also make sure your dracut.conf includes appropriate modules:

add_dracutmodules+=" iscsi lvm "
# I am using LVM on iSCSI. Ignore if just using normal GPT
install_items+=" /usr/bin/lsusb /usr/bin/lspci /usr/bin/iperf3 "
# Add additional files as you wish

I have effectively included as many core system utilities as possible in case I need to operate on the root device before leaving initrd.

HDCP everywhere under Mac OS / 1TR

Due to lack of desk space and monitors, my Mac mini is hooked up to an HDMI capture card. If your capture card can’t terminate HDCP encryption, anything the Mac Mini displays when running Mac OS / 1TR will be unviewable over the capture device even when there are no “copyrighted” contents being displayed at all. (Dammit. Apple. Why?)

Once M1N1 loads, the capture card should report non-HDCP encrypted content. After Linux kernel taking over the framebuffer, HDMI capture will remain unencrypted and functional.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.