AsahiLinux/m1n1: a bootloader and experimentation playground for Apple Silicon
A bootloader and experimentation playground for Apple Silicon
At a glance
- What is it?
- m1n1 is the low-level bootloader that Asahi Linux uses to bring Linux up on Apple Silicon Macs. It builds to a Mach-O or raw binary and runs payloads by concatenation, but it is a bring-up tool, not a general-purpose boot manager.
- Who is it for?
- Adopt m1n1 if you are bringing Linux up on an Apple Silicon machine or need a scratchpad for early hardware work, and you accept that installing it means reconfiguring the boot of an OS container with kmutil. Do not adopt it if you want a general-purpose boot menu for x86 hardware or a supported path on non-Apple machines: the README documents only Apple Silicon usage.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem m1n1 solves on Apple Silicon
Apple Silicon Macs do not boot the way a PC does. There is no conventional firmware interface that hands a Linux kernel a machine description and gets out of the way. m1n1 exists to fill that gap: it is a small bootloader that runs early, sets up what the kernel needs, and then hands control to a payload. The README describes the project plainly as a bootloader and experimentation playground for Apple Silicon, and the second half of that phrase matters. m1n1 is also where low-level work on these chips gets prototyped before it lands anywhere else.
The audience is narrow by design. If you are porting or debugging Linux on an M1 or later Mac, m1n1 is the layer you will spend time in. If you want a boot menu for a laptop that already runs Linux, this is not that tool. The repository is Python-heavy in its tooling but the bootloader itself is C and Rust, built freestanding with a cross-compiler. The MIT licence covers the project itself, with a long list of bundled third-party components under their own terms.
How m1n1 boots: payloads by concatenation
The mechanism is deliberately plain. m1n1 does not read a config file at boot to find a kernel. You concatenate the pieces into one file, in order, and m1n1 walks that stream. The README gives the exact form:
$ cat build/m1n1.macho Image.gz build/dtb/apple-j274.dtb initramfs.cpio.gz > m1n1-payload.macho
$ cat build/m1n1.bin Image.gz build/dtb/apple-j274.dtb initramfs.cpio.gz > m1n1-payload.binThe ordering rules are stated as constraints, not preferences. A kernel image must be compressed or must be the last payload. A devicetree blob may be uncompressed or compressed. An initramfs cpio image must be compressed. Compression is limited to gzip and xz. Get the order wrong and the stream is not parsed the way you expect, which is the trade-off of a format with no header and no manifest: it is trivial to produce and unforgiving to debug.
That design is the clearest signal of what m1n1 is for. A bootloader with a menu and a config parser is built for people who want to choose between installed systems. A bootloader that takes a concatenated byte stream is built for people who are constructing one specific boot and want to control every byte of it.
Building m1n1 from source
The README requires an aarch64-linux-gnu-gcc cross-compiler, or a native compiler if you are already on ARM64, plus the Rust target for bare-metal aarch64. Register the Rust target first:
$ rustup target add aarch64-unknown-none-softfloatThen clone with submodules and build. The recursive clone is not optional here, since the tree carries third-party components and vendored Rust crates:
$ git clone --recursive https://github.com/AsahiLinux/m1n1.git
$ cd m1n1
$ makeThe README states the output lands in build/m1n1.macho. If you want to see the actual compiler invocations, the README documents make V=1. On a native ARM64 Linux machine the documented invocation is make ARCH=, which clears the cross-compiler prefix. On macOS the README gives two routes: Homebrew with brew install llvm lld, or MacPorts with sudo port install llvm clang followed by sudo port select llvm llvm-mp-<version>. The Makefile confirms the Darwin path, setting USE_CLANG to 1 and locating llvm-config and ld.lld through brew when they are not already on PATH.
If you would rather not install the toolchain on your host, the repository ships a container setup. The Dockerfile is based on debian:bookworm-slim and installs the cross toolchain, device-tree-compiler and rustup with the bare-metal target already selected. The compose file mounts the repository into /m1n1:
$ podman-compose run m1n1 make
$ # or
$ docker-compose run m1n1 makeOne practical note on the host build: the Makefile adds -Wstack-usage=2048 to EXTRA_CFLAGS only in the GCC path, not the clang path. If you build with clang on macOS, that stack-usage warning is not in play, so a deep call chain that GCC would flag will pass silently.
Installing m1n1 and a first payload
The README points to the Asahi Linux wiki for usage detail and gives the two install commands directly. Which one you use depends on the macOS generation your OS container is based on, and this is the first thing to check. For a container based on macOS earlier than 12.1:
kmutil configure-boot -c m1n1.macho -v <path to your OS volume>For a container based on macOS 12.1 or later, the raw binary is required, along with an entry point and a lowest virtual address:
kmutil configure-boot -c m1n1.bin --raw --entry-point 2048 --lowest-virtual-address 0 -v <path to your OS volume>Both commands take the path to your OS volume as the final argument. The README does not document a rollback procedure for configure-boot, and it does not describe what the machine does if the payload fails to boot. Treat that as an open question to resolve before you run either command on hardware you care about, rather than as a detail you can pick up afterwards.
Once m1n1 is in place, a first real use is the concatenated payload from the previous section. Build the devicetree for your machine, compress a kernel and an initramfs, concatenate them in the documented order, and boot the result. If nothing comes up, the failure is almost always in the concatenation order or the compression of one of the parts, since there is no manifest to tell you which piece m1n1 rejected.
Where m1n1 is the wrong tool
m1n1 is tied to Apple Silicon and to the kmutil boot path. The README documents no other installation route and no other platform. If your hardware is x86, or an ARM board with U-Boot or EDK2 already on it, m1n1 has nothing to offer you, and the payload format will not help.
There is a second limit that is easy to miss. The concatenation format has no metadata, so it cannot express a boot menu, a timeout, a default entry, or a fallback. Everything about what boots is decided when you build the file. If you want to switch between two kernels on a running machine, you rebuild and reinstall rather than select at boot. That is a reasonable constraint for bring-up work and a poor fit for daily use.
Finally, the project describes itself as an experimentation playground, and that framing should set expectations. The README does not document rollback, does not document recovery from a failed boot, and does not promise stability for the interfaces it exposes. Anyone treating it as a supported, stable boot manager is reading a different project's documentation.
m1n1 compared with U-Boot
U-Boot is the obvious alternative for people who want a bootloader on ARM, and the difference in approach is stark. U-Boot carries a command line, environment variables, a boot script language, storage drivers for reading a kernel off disk, and a menu. It assumes the platform has firmware that loads it and a filesystem it can read.
m1n1 assumes almost none of that. It is loaded by the platform's own boot path, it receives a concatenated stream of bytes, and it runs them. There is no environment, no script, no filesystem. That is why it can run this early on Apple Silicon, where the pieces U-Boot depends on do not exist yet, and it is also why m1n1 cannot do the things U-Boot users take for granted. Choosing between them is not a matter of which is better; it is a matter of whether the platform gives you the firmware and storage abstractions U-Boot needs. On Apple Silicon at this stage, it does not.
Maintenance, upgrades and licensing
The repository is not archived, and the last push was on 2026-09-18. The most recent release listed is v1.6.1 from 2026-08-08. Upgrades are source upgrades: you pull the tree, re-run the recursive clone if submodules moved, rebuild, and reinstall with the same kmutil command. There is no package manager step and no versioned binary channel documented in the README.
The practical cost of an upgrade sits in the payload format and the install path, both of which are documented as fixed rules rather than negotiated interfaces. If a future release changes the concatenation requirements, your build scripts change with it. Budget for rebuilding and reinstalling rather than for an in-place update.
On licensing, m1n1 itself is MIT, which is permissive and imposes few obligations beyond keeping the notice. The complication is the vendored code. The README lists libfdt as dual BSD and GPL-2, minlzma as MIT, tinf as ZLIB, portions of arm-trusted-firmware as BSD, Doug Lea's malloc and portions of PDCLib as public domain under CC0, the Source Code Pro font under OFL-1.1, a dwc3 USB driver header that was BSD-or-GPLv2 dual-licensed, musl-libc floating point code as MIT, and Rust crates with licences in the vendor directory. If you redistribute a built m1n1, those terms travel with the corresponding components. This is a description of what the README states, not legal advice; if redistribution matters to you, read the files in 3rdparty_licenses/ yourself.
Editorial conclusion
Adopt m1n1 if you are bringing Linux up on an Apple Silicon machine or need a scratchpad for early hardware work, and you accept that installing it means reconfiguring the boot of an OS container with kmutil. Do not adopt it if you want a general-purpose boot menu for x86 hardware or a supported path on non-Apple machines: the README documents only Apple Silicon usage. Before you start, confirm which macOS generation your OS container is based on, because that decides whether you install m1n1.macho or m1n1.bin, and check that your toolchain can target aarch64-unknown-none-softfloat.
Frequently asked questions
Is Asahi Linux legal?
The README does not discuss the legal status of Asahi Linux. It states only that m1n1 is licensed under the MIT licence and lists the licences of the third-party components it embeds.
What is the best Linux system for an M1 Mac?
The README does not compare Linux distributions or recommend one. It describes m1n1 as a bootloader and experimentation playground for Apple Silicon, and points to the Asahi Linux wiki for usage information.
Is Asahi Linux available on the M1 Mac Mini?
The README does not list supported machines. It does show a devicetree path of build/dtb/apple-j274.dtb in its payload example, which is the identifier used for one Apple Silicon device.
Is Asahi Linux stable?
The README does not make a stability claim for Asahi Linux or for m1n1. It describes m1n1 as an experimentation playground, and it documents no rollback procedure for the kmutil configure-boot install step.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/asahilinux-m1n1)