(For programmers’ matters add a star)
Source: CSDN
The Apple M1 chip has sparked a huge interest in the industry, and the development of chips will influence the future direction of the industry. Today, let’s take a look at how to port Linux to the M1.
Since the release of the iPhone 6 in 2014, Apple has focused on building faster chips, emphasizing improvements in single-thread performance rather than loading more cores onto a single chip. Their internal hardware design team adopted this approach and produced versatile and unique chips, establishing their industry-leading position in architectural features.
In November 2020, Apple released new desktop computers equipped with the M1 processor, and many praised the outstanding performance of the system.
In fact, Linus Torvalds, the father of Linux, also responded to a question on the Real World Technologies forum about “what he thinks of the new (M1 chip) Apple computers” by saying:
If it runs Linux, I would absolutely love to have one.
Previously, CSDN reported that security consultant Hector Martin launched a project on the crowdfunding platform Patreon to port Linux to M1 Macs (https://www.patreon.com/marcan), which received a lot of responses from developers. The author of this article has also been working hard to provide insights for security researchers on how operating systems and programs run on Apple’s ARM processors. Therefore, when Apple decided to allow the installation of custom kernels on Macs with M1 processors, they decided to give it a try.
Starting to Port Linux to M1
Many components of the M1 are shared with Apple’s mobile SoC, so this is a good starting point. However, when writing Linux drivers, it was found that Apple’s SoC is actually very non-standard. Due to the flexibility of the author’s virtual environment, which can adapt to various models, on Linux, 64-bit ARM mainly relies on a well-defined set of components and firmware interfaces, but the M1 uses almost none of these components or firmware interfaces.
First, Apple’s CPU uses a different method to boot the operating system kernel. The bootloader (called iBoot) loads a Mach-O format executable target file that supports compression and is encapsulated in an ASN.1 signed IMG4 format. In contrast, Linux on a normal 64-bit ARM is booted by a standard binary image (which also supports compression and several container formats) or by a Windows-style “PE” executable file on UEFI platforms.
Once the CPU core starts, the real problem arises. On other 64-bit ARM systems, this step is usually done by calling firmware through the PSCI interface (some systems use a polling table but still require firmware). However, on the M1, the CPU core starts from an address specified by an MMIO register (the MMIO register is set to a specific offset by the kernel image and then locked by the bootloader) and directly begins to run the kernel.
Additionally, Apple has designed its own interrupt controller, the Apple Interrupt Controller (AIC), which is incompatible with any mainstream ARM GIC standard. Moreover, its timer interrupts are not connected to each CPU interrupt as is typical for ARM, but are routed to FIQ. FIQ is a difficult-to-understand architectural feature that was often used in older 32-bit ARM processors. Clearly, the Linux kernel does not support sending interrupts via FIQ, so we had to implement it ourselves.
Multiple processors in the system need to communicate with each other using a set of inter-processor interrupts (IPI). On older Apple SoCs, these interrupts were handled similarly to IRQs, i.e., executing MMIO and accessing the AIC. But on the new processors, Apple uses a set of processor core registers to distribute and notify IPI, which is also routed to FIQ. Therefore, support for FIQ is very important.
After addressing some other hardware features, the author’s team added a preloader as a stepping stone to start the processor cores, allowing them to set up the framebuffer and see the Linux penguin during boot.
Need More Input
Unfortunately, the author’s team was unable to use the UART lines on the M1 Mac, so they had to add a keyboard (and even a mouse) through other means. The M1 Mac Mini has three ways to achieve this: the built-in USB host on the M1 chip (providing Thunderbolt/USB interfaces), the xHCI USB host on PCIe (providing Type A interfaces), and Bluetooth.
The team did not intend to delve into Apple’s Bluetooth, but they noticed that it uses a non-standard PCIe protocol, and not only requires using the PCIe interface on the M1 chip but also requires writing a custom kernel driver for that protocol. This is not an ideal choice.
That said, they could only choose PCIe and use the standard kernel xHCI driver or use the built-in USB controller. Apple has long used the Synopsys DWC3 dual-role USB controller in its chips, and this controller has a Linux kernel driver. Unfortunately, Apple added custom logic to this controller, so a lot of work is needed here as well.
The M1’s PCIe and built-in DWC3 USB controller both use an IOMMU called DART. Apple has been improving its DART design, so the IOMMU features are quite complete. The latest version even supports sub-page memory protection, which has never been seen in other controllers.
To connect the USB ports on the M1 to the USB-C connector on the back of the Mac Mini, the team needed to use a chip on I2C (which means they needed to provide GPIO and I2C drivers), both of which used custom firmware.
After studying USB for a few days, they finally managed to connect to an external USB hub and successfully connected a keyboard, mouse, and flash drive, allowing them to run a normal Linux desktop version.
Operation Guide
Download Ubuntu rootfs
The first step to booting Linux on the Mac Mini M1 is to download the rootfs of the Ubuntu POC. They used the Raspberry Pi image because it is a live version of the USB boot image, so only minor modifications are needed.
Unzip the Image
You need at least a 16 GB external USB. Execute the following command to unzip the image:
tar -xjvf ubuntu-20.10-preinstalled-desktop-arm64+raspi.img.bz2
Then, use Disk Utility to find the name of the external USB. Finally, execute the following command to copy the image to the USB:
sudo dd if=ubuntu-20.10-preinstalled-desktop-arm64+raspi.img of=/dev/rYOURUSBDISK bs=1m
Connect to Mac
Insert the USB into the Mac Mini M1 via a USB-C adapter. Currently, Type A is not supported.
Boot to 1TR
To boot to 1TR (the real recovery operating system), turn off the Mac Mini M1, then hold the power button until you see “loading options”. Once loading is complete, select the terminal option from the top menu.
Install Custom Kernel
The next step is to install the custom kernel. The author’s team wrote a script to ease your burden. Just run:
/bin/bash -c "$(curl -fsSL https://downloads.corellium.info/linuxsetup.sh)"
The script will ask for a username and password. Once you see the “Kernel installed” prompt, you can reboot.
Login
After the system boots, you will be prompted to log in. The username is “pi”, and the password is “raspberry”. The root password is also “raspberry”.
Restore MacOS
If you want to restore to MacOS, just open the terminal in 1TR and execute bputil -n.
Reference link: https://corellium.com/blog/linux-m1
– EOF –
Recommended Reading Click the title to jump
1. Microsoft VS Code has 14 million users, while there are only 24 million developers worldwide
2. The spam-sending Maimai has finally lost the lawsuit, and netizens say: it should have been sentenced long ago
3. What is the experience of using an M1 MacBook as a primary development machine?
Follow “Programmers’ Matters” and add a star to not miss out on industry news

Likes and views are the biggest support ❤️