├── .editorconfig ├── .gitignore ├── .packit.yaml ├── LICENSE ├── Makefile ├── asahi-diagnose ├── asahi-fwupdate ├── dracut ├── dracut.conf.d │ ├── 10-asahi-noextgpu.conf │ └── 10-asahi.conf └── modules.d │ ├── 91kernel-modules-asahi │ └── module-setup.sh │ ├── 99asahi-dev-modules │ ├── install-asahi-dev-modules.sh │ ├── link-asahi-dev-modules.sh │ └── module-setup.sh │ └── 99asahi-firmware │ ├── install-asahi-firmware.sh │ ├── load-asahi-firmware.sh │ └── module-setup.sh ├── first-boot ├── functions.sh ├── initcpio ├── hooks │ └── asahi └── install │ └── asahi ├── libalpm └── hooks │ └── 95-m1n1-install.hook ├── macsmc-battery ├── systemd │ ├── macsmc-battery-charge-control-end-threshold.path │ └── macsmc-battery-charge-control-end-threshold.service └── udev │ └── 93-macsmc-battery-charge-control.rules ├── systemd └── first-boot.service ├── udev └── hwdb.d │ └── 65-autosuspend-override-asahi-sdhci.hwdb ├── update-grub └── update-m1n1 /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # Defaults 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | tab_width = 4 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | max_line_length = 100 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | /asahi-scripts-*\.src\.rpm 3 | /asahi-scripts-*\.tar\.gz 4 | /asahi-scripts\.spec 5 | /update-m1n1.sysconfig 6 | -------------------------------------------------------------------------------- /.packit.yaml: -------------------------------------------------------------------------------- 1 | # See the documentation for more information: 2 | # https://packit.dev/docs/configuration/ 3 | 4 | specfile_path: asahi-scripts.spec 5 | files_to_sync: 6 | - asahi-scripts.spec 7 | - .packit.yaml 8 | 9 | actions: 10 | # Fetch the specfile from Rawhide, disable rpmautospec and download config 11 | post-upstream-clone: "bash -c \"curl -s https://src.fedoraproject.org/rpms/asahi-scripts/raw/main/f/asahi-scripts.spec | sed -e '/^%autochangelog$/d' > asahi-scripts.spec && curl -s --remote-name https://src.fedoraproject.org/rpms/asahi-scripts/raw/main/f/update-m1n1.sysconfig\"" 12 | 13 | srpm_build_deps: 14 | - bash 15 | - curl 16 | - sed 17 | 18 | jobs: 19 | - job: copr_build 20 | trigger: commit 21 | owner: "@asahi" 22 | project: packit-builds 23 | targets: 24 | - fedora-all-aarch64 25 | - fedora-rawhide-i386 26 | - fedora-rawhide-ppc64le 27 | - fedora-rawhide-s390x 28 | - fedora-rawhide-x86_64 29 | 30 | - job: copr_build 31 | trigger: pull_request 32 | owner: "@asahi" 33 | project: packit-builds 34 | targets: 35 | - fedora-all-aarch64 36 | - fedora-rawhide-i386 37 | - fedora-rawhide-ppc64le 38 | - fedora-rawhide-s390x 39 | - fedora-rawhide-x86_64 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright The Asahi Linux Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX=/usr/local 2 | SYS_PREFIX=$(PREFIX) 3 | CONFIG_DIR=/etc/default 4 | BIN_DIR=$(PREFIX)/bin 5 | SCRIPTS=asahi-diagnose asahi-fwupdate update-m1n1 6 | ARCH_SCRIPTS=update-grub first-boot 7 | UNITS=first-boot.service 8 | MULTI_USER_WANTS=first-boot.service 9 | DRACUT_CONF_DIR=$(PREFIX)/lib/dracut/dracut.conf.d 10 | DRACUT_MODULES_DIR=$(PREFIX)/lib/dracut/modules.d 11 | SYSTEMD_UNIT_DIR=$(PREFIX)/lib/systemd/system 12 | UDEV_RULES_DIR=$(PREFIX)/lib/udev/rules.d 13 | UDEV_HWDB_DIR=$(PREFIX)/lib/udev/hwdb.d 14 | BUILD_SCRIPTS=$(addprefix build/,$(SCRIPTS)) 15 | BUILD_ARCH_SCRIPTS=$(addprefix build/,$(ARCH_SCRIPTS)) 16 | 17 | all: $(BUILD_SCRIPTS) $(BUILD_ARCH_SCRIPTS) 18 | 19 | build/%: % 20 | @[ ! -e build ] && mkdir -p build || true 21 | sed -e s,/etc/default,$(CONFIG_DIR),g "$<" > "$@" 22 | chmod +x "$@" 23 | 24 | clean: 25 | rm -rf build 26 | 27 | install: all 28 | install -d $(DESTDIR)$(BIN_DIR)/ 29 | install -m0755 -t $(DESTDIR)$(BIN_DIR)/ $(BUILD_SCRIPTS) 30 | install -dD $(DESTDIR)/etc 31 | install -dD $(DESTDIR)$(PREFIX)/share/asahi-scripts 32 | install -m0644 -t $(DESTDIR)$(PREFIX)/share/asahi-scripts functions.sh 33 | install -dD $(DESTDIR)/$(SYS_PREFIX)/lib/firmware/vendor 34 | 35 | install-mkinitcpio: install 36 | install -dD $(DESTDIR)$(PREFIX)/lib/initcpio/install 37 | install -m0644 -t $(DESTDIR)$(PREFIX)/lib/initcpio/install initcpio/install/asahi 38 | install -dD $(DESTDIR)$(PREFIX)/lib/initcpio/hooks 39 | install -m0644 -t $(DESTDIR)$(PREFIX)/lib/initcpio/hooks initcpio/hooks/asahi 40 | 41 | install-dracut: install 42 | install -dD $(DESTDIR)$(DRACUT_CONF_DIR) 43 | install -m0644 -t $(DESTDIR)$(DRACUT_CONF_DIR) dracut/dracut.conf.d/10-asahi.conf 44 | install -dD $(DESTDIR)$(DRACUT_MODULES_DIR)/91kernel-modules-asahi 45 | install -m0755 -t $(DESTDIR)$(DRACUT_MODULES_DIR)/91kernel-modules-asahi dracut/modules.d/91kernel-modules-asahi/module-setup.sh 46 | install -dD $(DESTDIR)$(DRACUT_MODULES_DIR)/99asahi-firmware 47 | install -m0755 -t $(DESTDIR)$(DRACUT_MODULES_DIR)/99asahi-firmware dracut/modules.d/99asahi-firmware/install-asahi-firmware.sh 48 | install -m0755 -t $(DESTDIR)$(DRACUT_MODULES_DIR)/99asahi-firmware dracut/modules.d/99asahi-firmware/load-asahi-firmware.sh 49 | install -m0755 -t $(DESTDIR)$(DRACUT_MODULES_DIR)/99asahi-firmware dracut/modules.d/99asahi-firmware/module-setup.sh 50 | 51 | install-macsmc-battery: install 52 | install -dD $(DESTDIR)$(SYSTEMD_UNIT_DIR) 53 | install -dD $(DESTDIR)$(UDEV_RULES_DIR) 54 | install -m0755 -t $(DESTDIR)$(SYSTEMD_UNIT_DIR) macsmc-battery/systemd/macsmc-battery-charge-control-end-threshold.path 55 | install -m0755 -t $(DESTDIR)$(SYSTEMD_UNIT_DIR) macsmc-battery/systemd/macsmc-battery-charge-control-end-threshold.service 56 | install -m0644 -t $(DESTDIR)$(UDEV_RULES_DIR) macsmc-battery/udev/93-macsmc-battery-charge-control.rules 57 | 58 | install-udev-hwdb: install 59 | install -dD $(DESTDIR)$(UDEV_HWDB_DIR) 60 | install -m0644 -t $(DESTDIR)$(UDEV_HWDB_DIR) udev/hwdb.d/65-autosuspend-override-asahi-sdhci.hwdb 61 | 62 | install-arch: install install-mkinitcpio install-macsmc-battery install-udev-hwdb 63 | install -m0755 -t $(DESTDIR)$(BIN_DIR)/ $(BUILD_ARCH_SCRIPTS) 64 | install -dD $(DESTDIR)$(PREFIX)/lib/systemd/system 65 | install -dD $(DESTDIR)$(PREFIX)/lib/systemd/system/{multi-user,sysinit}.target.wants 66 | install -m0644 -t $(DESTDIR)$(PREFIX)/lib/systemd/system $(addprefix systemd/,$(UNITS)) 67 | ln -sf $(addprefix $(PREFIX)/lib/systemd/system/,$(MULTI_USER_WANTS)) \ 68 | $(DESTDIR)$(PREFIX)/lib/systemd/system/multi-user.target.wants/ 69 | install -dD $(DESTDIR)$(PREFIX)/share/libalpm/hooks 70 | install -m0644 -t $(DESTDIR)$(PREFIX)/share/libalpm/hooks libalpm/hooks/95-m1n1-install.hook 71 | 72 | install-fedora: install install-dracut install-macsmc-battery install-udev-hwdb 73 | 74 | uninstall: 75 | rm -f $(addprefix $(DESTDIR)$(BIN_DIR)/,$(SCRIPTS)) 76 | rm -rf $(DESTDIR)$(PREFIX)/share/asahi-scripts 77 | 78 | uninstall-mkinitcpio: 79 | rm -f $(DESTDIR)$(PREFIX)/lib/initcpio/install/asahi 80 | rm -f $(DESTDIR)$(PREFIX)/lib/initcpio/hooks/asahi 81 | 82 | uninstall-dracut: 83 | rm -f $(DESTDIR)$(DRACUT_CONF_DIR)/10-asahi.conf 84 | 85 | uninstall-macsmc-battery: 86 | rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/macsmc-battery-charge-control-end-threshold.path 87 | rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/macsmc-battery-charge-control-end-threshold.service 88 | rm -f $(DESTDIR)$(UDEV_RULES_DIR)/93-macsmc-battery-charge-control.rules 89 | 90 | uninstall-udev-hwdb: 91 | rm -f $(DESTDIR)$(UDEV_HWDB_DIR)/65-autosuspend-override-asahi-sdhci.hwdb 92 | 93 | uninstall-arch: uninstall-mkinitcpio uninstall-macsmc-battery uninstall-udev-hwdb 94 | rm -f $(addprefix $(DESTDIR)$(BIN_DIR)/,$(ARCH_SCRIPTS)) 95 | rm -f $(addprefix $(DESTDIR)$(PREFIX)/lib/systemd/system/,$(UNITS)) 96 | rm -f $(addprefix $(DESTDIR)$(PREFIX)/lib/systemd/system/multi-user.target.wants/,$(MULTI_USER_WANTS)) 97 | rm -f $(DESTDIR)$(PREFIX)/share/libalpm/hooks/95-m1n1-install.hook 98 | 99 | uninstall-fedora: uninstall-dracut uninstall-macsmc-battery uninstall-udev-hwdb 100 | 101 | .PHONY: clean \ 102 | install \ 103 | install-mkinitcpio \ 104 | install-dracut \ 105 | install-macsmc-battery \ 106 | install-udev-hwdb \ 107 | install-arch \ 108 | install-fedora \ 109 | uninstall \ 110 | uninstall-mkinitcpio \ 111 | uninstall-dracut \ 112 | uninstall-macsmc-battery \ 113 | uninstall-udev-hwdb \ 114 | uninstall-arch \ 115 | uninstall-fedora 116 | -------------------------------------------------------------------------------- /asahi-diagnose: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | log() { 4 | echo "$@" 5 | } 6 | 7 | dt() { 8 | p=/proc/device-tree/"$1" 9 | if [ ! -e "$p" ]; then 10 | echo "(missing)" 11 | else 12 | cat "$p" | tr "\0" " " | sed -e 's/ $//g'; echo 13 | fi 14 | } 15 | 16 | banner() { 17 | cat < /dev/null \ 84 | && echo "yes" \ 85 | || echo "no" 86 | } 87 | pro_audio=$(check_proaudio) 88 | 89 | # Check for Configs in /etc/ (installed before mid 2023) 90 | check_audio_oldconfs() { 91 | [ -e /etc/pipewire/pipewire.conf.d/*asahi* ] \ 92 | || [ -e /etc/wireplumber/policy.lua.d/99-asahi-policy.lua ] \ 93 | && echo "yes" \ 94 | || echo "no" 95 | } 96 | old_conf=$(check_audio_oldconfs) 97 | 98 | # Check for the racy 99-asahi* build (installed before ~Oct 2023) 99 | check_audio_oldbuild() { 100 | [ -e /usr/share/wireplumber/policy.lua.d/99-asahi-policy.lua ] \ 101 | && echo "yes" \ 102 | || echo "no" 103 | } 104 | racy_build=$(check_audio_oldbuild) 105 | 106 | # Check if snd-soc-macaudio.please_blow_up_my_speakers was requested 107 | check_audio_macaudio() { 108 | grep "0" /sys/module/snd_soc_macaudio/parameters/please_blow_up_my_speakers > /dev/null \ 109 | && echo "no" \ 110 | || echo "yes" 111 | } 112 | bad_macaudio_params=$(check_audio_macaudio) 113 | 114 | # Check that snd-soc-tas2764.apple_quirks=0x3f is being applied 115 | check_audio_tas2764() { 116 | [ -e /sys/module/snd_soc_tas2764/ ] && ( 117 | grep "63" /sys/module/snd_soc_tas2764/parameters/apple_quirks > /dev/null \ 118 | && echo "yes" \ 119 | || echo "no" 120 | ) || echo "N/A" 121 | } 122 | tas2764_quirks=$(check_audio_tas2764) 123 | 124 | audio_config() { 125 | cat </dev/null | sort -u) 179 | \`\`\` 180 | 181 | EOF 182 | } 183 | 184 | module_parameters() { 185 | echo "## Module parameters" 186 | for mod in asahi hid_apple hid_magicmouse; do 187 | [ ! -e /sys/module/$mod/parameters/ ] && continue 188 | echo " $mod" 189 | for param in /sys/module/$mod/parameters/*; do 190 | echo " $(basename "$param")=$(cat "$param" | tr -d '\0')" 191 | done 192 | echo 193 | done 194 | echo 195 | } 196 | 197 | logfile() { 198 | f="$1" 199 | lines="$2" 200 | [ -e "$1" ] || return 201 | echo "## Log file: \`$f\`" 202 | echo '```' 203 | if [ -z "$lines" ]; then 204 | cat "$f" 205 | else 206 | tail -n "$lines" "$f" 207 | fi 208 | echo '```' 209 | echo 210 | } 211 | 212 | environment() { 213 | echo "## Environment" 214 | set | grep -E 'MESA|AGX|ASAHI|XDG_SESSION_TYPE|DISPLAY|TERM|LANG|LOCALE|LC_' | sed 's/^/ /' 215 | echo 216 | } 217 | 218 | diagnose() { 219 | f="$1" 220 | 221 | >$f 222 | 223 | log "Collecting system diagnostic information..." 224 | log 225 | 226 | ( 227 | exec >"$f" 2>&1 228 | banner 229 | device_info 230 | firmware_versions 231 | boot_config 232 | system_info 233 | audio_config 234 | environment 235 | getfile /proc/mounts "Mounts" 236 | package_versions 237 | cmd lsblk "Block devices" 238 | cmd lspci "PCI devices" 239 | getfile /proc/bus/input/devices "Input devices" 240 | cmd lsmod "Loaded modules" 241 | module_parameters 242 | cmd 'journalctl -b 0 -tkernel' "Kernel log" 243 | cmd 'journalctl -b -1 -tkernel' "Kernel log (last boot)" 244 | logfile /var/log/Xorg.0.log 245 | logfile /var/log/pacman.log 500 246 | ) 247 | 248 | log "Saved diagnostic information to $f" 249 | 250 | if [ "$macaudio_profile" != "HiFi" -a "$macaudio_profile" != "Default" ]; then 251 | echo 252 | echo "Pipewire macaudio profile is \"${macaudio_profile}\"." 253 | echo "Headphones and speakers will not work. Select the \"Default\" or \"HiFi\" profile." 254 | fi 255 | 256 | if [ "$pro_audio" = "yes" ] || \ 257 | [ "$old_conf" = "yes" ] || \ 258 | [ "$racy_build" = "yes" ] || \ 259 | [ "$bad_macaudio_params" = "yes" ] || \ 260 | [ "$tas2764_quirks" = "no" ]; then 261 | echo 262 | echo "!! IMPORTANT !!" 263 | echo "Your audio configuration is in an invalid state. It is likely that you tried to" 264 | echo "enable speakers early, despite numerous and very explicit warnings not to do so." 265 | echo "Potential reason(s) you are seeing this message: " 266 | ( 267 | [ "$pro_audio" = "yes" ] && echo " - The Pro Audio profile is/was enabled for the internal speakers." 268 | [ "$old_conf" = "yes" ] && echo " - You have files in /etc/ from a prerelease version of asahi-audio." 269 | [ "$racy_build" = "yes" ] && echo " - You have files in /usr/share/ from a prerelease version of asahi-audio." 270 | [ "$bad_macaudio_params" = "yes" ] && echo " - You have tried to manually circumvent our kernel-level safety controls." 271 | [ "$tas2764_quirks" = "no" ] && echo " - Required speaker codec settings are not being applied." 272 | ) 273 | echo "Please go to https://asahilinux.org/docs/sw/undoing-early-speaker-hacks/ for fixes." 274 | echo "Do NOT file audio-related bugs until you have tried ALL fixes suggested at the page above." 275 | echo "Your bugs will be ignored and you will not be assisted." 276 | fi 277 | 278 | 279 | plat="$(cat /proc/device-tree/compatible | sed -re 's/.*apple,(t....).*/\1/g')" 280 | ver="$(tr -d '\0' /dev/null 2>&1; then 321 | echo 322 | echo "** WARNING! **" 323 | echo "The asahi-platform-metapackage package is not installed, you may be missing" 324 | echo "required platform dependencies. See https://discussion.fedoraproject.org/t/95301" 325 | echo "for how to fix it." 326 | fi 327 | fi 328 | } 329 | 330 | if [ -z "$1" ]; then 331 | diagnose "$HOME/asahi-diagnose-$(date +%Y%m%d-%H%M%S).txt" 332 | elif [ "$1" = "-" ]; then 333 | diagnose /dev/stdout 334 | else 335 | diagnose "$1" 336 | fi 337 | -------------------------------------------------------------------------------- /asahi-fwupdate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | set -eu 5 | 6 | unset PYTHON 7 | 8 | [ -e /etc/default/asahi-fwupdate ] && . /etc/default/asahi-fwupdate 9 | 10 | : "${ASAHIFW:=}" 11 | : "${VENDORFW:=}" 12 | : "${VENDORFWTMP:=/run/.vendorfw-tmp}" 13 | : "${PYTHON:=/usr/bin/python3}" 14 | 15 | if [ -e "$(dirname "$0")"/functions.sh ]; then 16 | . "$(dirname "$0")"/functions.sh 17 | else 18 | . /usr/share/asahi-scripts/functions.sh 19 | fi 20 | 21 | umount=false 22 | 23 | if [ -z "$ASAHIFW" ] && [ -z "$VENDORFW" ]; then 24 | mount_sys_esp /run/.system-efi 25 | ASAHIFW="/run/.system-efi/asahi/" 26 | VENDORFW="/run/.system-efi/vendorfw" 27 | umount=true 28 | fi 29 | 30 | if [ ! -e "${ASAHIFW}/all_firmware.tar.gz" ]; then 31 | echo "No firmware tarball found, skipping extraction" 32 | exit 0 33 | fi 34 | 35 | if [ ! -d "$VENDORFW" ]; then 36 | mkdir -p "$VENDORFW" 37 | fi 38 | 39 | if [ ! -d "$VENDORFWTMP" ]; then 40 | mkdir -p "$VENDORFWTMP" 41 | fi 42 | 43 | echo "Upgrading vendor firmware package" 44 | asahi-fwextract "$ASAHIFW" "$VENDORFWTMP" 45 | rm -rf "$VENDORFW".new 46 | mv "${VENDORFWTMP}" "$VENDORFW".new 47 | rm -rf "$VENDORFW" 48 | mv "$VENDORFW".new "$VENDORFW" 49 | rm -rf "$VENDORFWTMP" 50 | echo "Firmware upgraded" 51 | 52 | $umount && umount /run/.system-efi 53 | true 54 | -------------------------------------------------------------------------------- /dracut/dracut.conf.d/10-asahi-noextgpu.conf: -------------------------------------------------------------------------------- 1 | # dracut config fragment to omit external PCIe GPUs 2 | # as of June 2024 PCIe tunneling over USB4/TB is not supported so it is 3 | # pointless to include those. Even when PCIe tunneling works PCIe GPUs are 4 | # probably not suppported and using them as primary display will not be a 5 | # supported configuration. 6 | # 7 | # This saves over 60 MB of firmware files in the initramfs on 8 | # Fedora-Asahi-Remix (Fedora 40, Kernel 6.9). 9 | # TODO: omit Xe drivers once their build is enabled on arm64. 10 | 11 | omit_drivers+=" amdgpu nouveau radeon " 12 | -------------------------------------------------------------------------------- /dracut/dracut.conf.d/10-asahi.conf: -------------------------------------------------------------------------------- 1 | # Modules necessary for using Linux on Apple Silicon Macs 2 | # are handled in the module kernel-modules-asahi since add_drivers can't 3 | # handle missing modules 4 | 5 | # dwc3 instantiates xHCI asynchronously. To make things like init=/bin/sh work where udev is no longer running, force load this one. 6 | force_drivers+=" xhci-plat-hcd " 7 | 8 | # For Apple firmware 9 | add_dracutmodules+=" asahi-firmware kernel-modules-asahi " 10 | -------------------------------------------------------------------------------- /dracut/modules.d/91kernel-modules-asahi/module-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # called by dracut 4 | installkernel() { 5 | # For NVMe & SMC 6 | hostonly='' instmods apple-mailbox 7 | 8 | # For NVMe 9 | hostonly='' instmods nvme_apple 10 | 11 | # For USB and HID 12 | hostonly='' instmods pinctrl-apple-gpio 13 | 14 | # SMC core 15 | hostonly='' instmods macsmc macsmc-rtkit 16 | 17 | # For USB 18 | hostonly='' instmods \ 19 | i2c-apple \ 20 | i2c-pasemi-platform \ 21 | tps6598x \ 22 | apple-dart \ 23 | dwc3 \ 24 | dwc3-of-simple \ 25 | nvmem-apple-efuses \ 26 | phy-apple-atc \ 27 | xhci-plat-hcd \ 28 | xhci-pci \ 29 | pcie-apple \ 30 | gpio_macsmc 31 | 32 | # For RTC 33 | hostonly='' instmods rtc-macsmc simple-mfd-spmi spmi-apple-controller nvmem_spmi_mfd 34 | 35 | # For HID 36 | hostonly='' instmods spi-apple spi-hid-apple spi-hid-apple-of 37 | 38 | # For MTP HID 39 | hostonly='' instmods apple-dockchannel dockchannel-hid apple-rtkit-helper 40 | 41 | # For DP / HDMI audio 42 | hostonly='' instmods apple-sio 43 | 44 | # For DPTX and HDMI displays 45 | hostonly='' instmods mux-apple-display-crossbar phy-apple-dptx 46 | } 47 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-dev-modules/install-asahi-dev-modules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh 5 | 6 | if [ ! -d /$(uname -r) ]; then 7 | return 0 8 | fi 9 | 10 | DESTDIR="/sysroot/lib/modules/$(uname -r)" 11 | 12 | info ":: Asahi: Installing dev kernel modules to root filesystem..." 13 | if [ ! -e ${DESTDIR} ]; then 14 | if [ ! -w /sysroot ]; then 15 | error ":: Asahi: root fs not writable!" 16 | return 0 17 | fi 18 | 19 | mkdir -p ${DESTDIR} 20 | fi 21 | 22 | mount -t tmpfs -o mode=0755,size=192m dev-modules /${DESTDIR} 23 | cp -pr /$(uname -r)/* ${DESTDIR}/ 24 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-dev-modules/link-asahi-dev-modules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh 5 | 6 | if [ -d /$(uname -r) ]; then 7 | info ":: Asahi: dev modules present, link them into system" 8 | ln -s /$(uname -r) /lib/modules/ 9 | fi 10 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-dev-modules/module-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | # called by dracut 5 | check() { 6 | if [ -n "$hostonly" ] && [ ! -e /proc/device-tree/chosen/asahi,efi-system-partition ]; then 7 | return 0 8 | elif [ -z "$hostonly" ]; then 9 | return 0 10 | else 11 | return 255 12 | fi 13 | } 14 | 15 | # called by dracut 16 | depends() { 17 | echo fs-lib 18 | return 0 19 | } 20 | 21 | # called by dracut 22 | install() { 23 | inst_multiple cp ln mkdir mount 24 | inst_hook pre-udev 99 "${moddir}/link-asahi-dev-modules.sh" 25 | inst_hook pre-pivot 99 "${moddir}/install-asahi-dev-modules.sh" 26 | } 27 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-firmware/install-asahi-firmware.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh 5 | 6 | info ":: Asahi: Installing vendor firmware to root filesystem..." 7 | if [ ! -d /sysroot/lib/firmware/vendor ]; then 8 | warn ":: Asahi: Vendor firmware directory missing on the root filesystem!" 9 | return 1 10 | fi 11 | mount -t tmpfs -o mode=0755 vendorfw /sysroot/lib/firmware/vendor 12 | cp -a /vendorfw/* /vendorfw/.vendorfw.manifest /sysroot/lib/firmware/vendor 13 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-firmware/load-asahi-firmware.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh 5 | 6 | if [ -e /vendorfw ]; then 7 | info ":: Asahi: Vendor firmware was loaded by the bootloader" 8 | return 0 9 | fi 10 | 11 | if [ ! -e /proc/device-tree/chosen/asahi,efi-system-partition ]; then 12 | info ":: Asahi: Missing asahi,efi-system-partition variable, firmware will not be loaded!" 13 | return 0 14 | fi 15 | 16 | info ":: Asahi: Triggering early load of NVMe modules..." 17 | modprobe apple-mailbox 18 | modprobe nvme-apple 19 | 20 | for i in $(seq 0 50); do 21 | [ -e /sys/bus/platform/drivers/nvme-apple/*.nvme/nvme/nvme*/nvme*n1/ ] && break 22 | sleep 0.1 23 | done 24 | 25 | if [ ! -e /sys/bus/platform/drivers/nvme-apple/*.nvme/nvme/nvme*/nvme*n1/ ]; then 26 | warn ":: Asahi: Timed out waiting for NVMe device" 27 | return 1 28 | fi 29 | 30 | # If the above exists, hopefully the /dev device exists and this will work 31 | info ":: Asahi: Unpacking vendor firmware into initramfs..." 32 | 33 | VENDORFW="/run/.system-efi/vendorfw/" 34 | 35 | ( 36 | . /usr/share/asahi-scripts/functions.sh 37 | mount_sys_esp /run/.system-efi 38 | ) 39 | 40 | if [ ! -e "$VENDORFW/firmware.cpio" ]; then 41 | warn ":: Asahi: Vendor firmware not found in ESP." 42 | umount /run/.system-efi 43 | return 1 44 | fi 45 | 46 | ( cd /; cpio --quiet -i < "$VENDORFW/firmware.cpio" ) 47 | info ":: Asahi firmware unpacked successfully" 48 | umount /run/.system-efi 49 | -------------------------------------------------------------------------------- /dracut/modules.d/99asahi-firmware/module-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | # called by dracut 5 | check() { 6 | if [ -n "$hostonly" ] && [ ! -e /proc/device-tree/chosen/asahi,efi-system-partition ]; then 7 | return 0 8 | elif [ -z "$hostonly" ]; then 9 | return 0 10 | else 11 | return 255 12 | fi 13 | } 14 | 15 | # called by dracut 16 | depends() { 17 | echo fs-lib 18 | return 0 19 | } 20 | 21 | # called by dracut 22 | installkernel() { 23 | instmods apple-mailbox nvme-apple vfat 24 | } 25 | 26 | # called by dracut 27 | install() { 28 | inst_dir "/lib/firmware" 29 | ln_r "/vendorfw" "/lib/firmware/vendor" 30 | asahiscriptsdir="/usr/share/asahi-scripts" 31 | inst_dir $asahiscriptsdir 32 | $DRACUT_CP -R -L -t "${initdir}/${asahiscriptsdir}" "${dracutsysrootdir}${asahiscriptsdir}"/* 33 | inst_multiple cpio cut dirname grep mkdir modprobe mount seq sleep umount 34 | inst_hook pre-udev 10 "${moddir}/load-asahi-firmware.sh" 35 | inst_hook cleanup 99 "${moddir}/install-asahi-firmware.sh" 36 | } 37 | -------------------------------------------------------------------------------- /first-boot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | set -e 5 | 6 | root_dev=$(findmnt -n -o SOURCE /) 7 | efi_dev=$(findmnt -n -o SOURCE /boot/efi) 8 | 9 | if [ -e "$root_dev" ]; then 10 | echo "Randomizing root filesystem UUID..." 11 | tune2fs -U random "$root_dev" 12 | 13 | root_uuid="$(blkid -c /dev/null "$root_dev" -o export | grep '^UUID=')" 14 | echo "Root filesystem: $root_uuid" 15 | echo 16 | fi 17 | 18 | if [ -e "$efi_dev" ] && \ 19 | blkid "$efi_dev" | grep -q 'TYPE="vfat"'; then 20 | 21 | echo "Randomizing EFI system partition UUID..." 22 | # Ugly... why isn't there a command to do this? 23 | ssize="$(blockdev --getss "$efi_dev")" 24 | dd bs=1 seek=67 count=4 conv=notrunc if=/dev/urandom of="$efi_dev" 25 | dd bs=1 skip=67 seek=$((67+6*$ssize)) count=4 conv=notrunc if="$efi_dev" of="$efi_dev" 26 | 27 | efi_uuid="$(blkid -c /dev/null "$efi_dev" -o export | grep '^UUID=')" 28 | echo "EFI partition: $efi_uuid" 29 | echo 30 | fi 31 | 32 | if [ ! -z "$root_uuid" ] && [ ! -z "$efi_uuid" ]; then 33 | echo "Regenerating /etc/fstab..." 34 | tee /etc/fstab <&2 16 | } 17 | 18 | warn() { 19 | echo "$@" 1>&2 20 | } 21 | 22 | mount_sys_esp() { 23 | set -e 24 | mountpoint="$1" 25 | 26 | mkdir -p "$mountpoint" 27 | while grep -q " $mountpoint " /proc/mounts; do 28 | umount "$mountpoint" 29 | done 30 | 31 | esp_uuid="$(cat /proc/device-tree/chosen/asahi,efi-system-partition 2>/dev/null | sed 's/\x00//')" 32 | if [ -e /boot/efi/.builder ] || [ -e /boot/.builder ] || [ -z "$esp_uuid" ]; then 33 | if [ -e "/boot/efi/m1n1" ]; then 34 | bootmnt="/boot/efi" 35 | elif [ -e "/boot/m1n1" ]; then 36 | bootmnt="/boot" 37 | else 38 | warn "ESP not found and cannot determine ESP PARTUUID." 39 | warn "Make sure that your m1n1 has the right asahi,efi-system-partition configuration," 40 | warn "or that your ESP is mounted at /boot/efi or /boot." 41 | return 1 42 | fi 43 | mount --bind "$bootmnt" "$mountpoint" 44 | warn "System ESP not identified in device tree, using $bootmnt" 45 | else 46 | mount "PARTUUID=$esp_uuid" "$mountpoint" 47 | fi 48 | dev="$(grep "$mountpoint" /proc/mounts | cut -d" " -f1)" 49 | info "Mounted System ESP $dev at $mountpoint" 50 | } 51 | 52 | mount_boot_esp() { 53 | set -e 54 | mountpoint="$1" 55 | 56 | mkdir -p "$mountpoint" 57 | while grep -q " $mountpoint " /proc/mounts; do 58 | umount "$mountpoint" 59 | done 60 | 61 | if [ -e "/boot/efi/efi/boot" ]; then 62 | mount --bind "/boot/efi" "$mountpoint" 63 | elif [ -e "/boot/efi/boot" ]; then 64 | mount --bind "/boot" "$mountpoint" 65 | else 66 | esp_uuid="$(cat /proc/device-tree/chosen/asahi,efi-system-partition | sed 's/\x00//')" 67 | 68 | if [ -z "$esp_uuid" ]; then 69 | echo "Boot ESP not found and cannot determine ESP PARTUUID." 70 | echo "Make sure your ESP is mounted at /boot/efi or /boot," 71 | echo "or that your m1n1 has the right asahi,efi-system-partition configuration." 72 | return 1 73 | fi 74 | 75 | mount "PARTUUID=$esp_uuid" "$mountpoint" 76 | fi 77 | info "Mounted Boot ESP at $mountpoint" 78 | } 79 | -------------------------------------------------------------------------------- /initcpio/hooks/asahi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ash 2 | # SPDX-License-Identifier: MIT 3 | 4 | run_earlyhook() { 5 | if [ -e /vendorfw ]; then 6 | msg ":: Asahi: Vendor firmware was loaded by the bootloader" 7 | return 0 8 | fi 9 | 10 | if [ ! -e /proc/device-tree/chosen/asahi,efi-system-partition ]; then 11 | msg ":: Asahi: Missing asahi,efi-system-partition variable, firmware will not be loaded!" 12 | return 1 13 | fi 14 | 15 | msg ":: Asahi: Triggering early load of NVMe modules..." 16 | modprobe apple-mailbox 17 | modprobe nvme-apple 18 | modprobe xhci-plat-hcd 19 | 20 | for i in $(seq 0 50); do 21 | [ -e /sys/bus/platform/drivers/nvme-apple/*.nvme/nvme/nvme*/nvme*n1/ ] && break 22 | sleep 0.1 23 | done 24 | 25 | if [ ! -e /sys/bus/platform/drivers/nvme-apple/*.nvme/nvme/nvme*/nvme*n1/ ]; then 26 | err "Timed out waiting for NVMe device" 27 | return 1 28 | fi 29 | 30 | # If the above exists, hopefully the /dev device exists and this will work 31 | 32 | msg ":: Asahi: Unpacking vendor firmware into initramfs..." 33 | 34 | VENDORFW="/run/.system-efi/vendorfw/" 35 | 36 | ( 37 | . /usr/share/asahi-scripts/functions.sh 38 | mount_sys_esp /run/.system-efi 39 | ) 40 | 41 | if [ ! -e "$VENDORFW/firmware.cpio" ]; then 42 | msg ":: Asahi: Vendor firmware not available in ESP!" 43 | umount /run/.system-efi 44 | return 1 45 | fi 46 | 47 | ( cd /; cpio -i < "$VENDORFW/firmware.cpio" ) 48 | umount /run/.system-efi 49 | 50 | msg ":: Asahi: Vendor firmware unpacked successfully" 51 | } 52 | 53 | run_latehook() { 54 | [ -e /vendorfw ] || return 55 | msg ":: Asahi: Copying vendor firmware to tmpfs under root filesystem..." 56 | mkdir -p /new_root/lib/firmware/vendor 57 | mount -t tmpfs -o mode=0755 vendorfw /new_root/lib/firmware/vendor 58 | cp -r /vendorfw/* /vendorfw/.vendorfw.manifest /new_root/lib/firmware/vendor 59 | } 60 | -------------------------------------------------------------------------------- /initcpio/install/asahi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT 3 | 4 | build() { 5 | local filter 6 | 7 | # For NVMe & SMC 8 | add_module apple-mailbox? 9 | 10 | # For NVMe 11 | add_module nvme-apple? 12 | 13 | # For USB and HID 14 | add_module pinctrl-apple-gpio? 15 | 16 | # SMC core 17 | map add_module macsmc? macsmc-rtkit? 18 | 19 | # For USB 20 | map add_module i2c-pasemi-platform? tps6598x? apple-dart? dwc3? dwc3-of-simple? \ 21 | nvmem-apple-efuses? phy-apple-atc? xhci-plat-hcd? xhci-pci? pcie-apple? gpio_macsmc? 22 | 23 | # For HID 24 | map add_module spi-apple? spi-hid-apple? spi-hid-apple-of? 25 | 26 | # For RTC 27 | map add_module rtc-macsmc? simple-mfd-spmi? spmi-apple-controller? \ 28 | nvmem_spmi_mfd? 29 | 30 | # For MTP HID 31 | map add_module apple-dockchannel? dockchannel-hid? apple-rtkit-helper? 32 | 33 | # Hook dependencies 34 | add_full_dir /usr/share/asahi-scripts 35 | 36 | # Firmware update script 37 | add_runscript 38 | add_dir /lib/firmware 39 | add_symlink /lib/firmware/vendor /vendorfw 40 | } 41 | 42 | help() { 43 | cat < /etc/udev/macsmc-battery.conf' 7 | -------------------------------------------------------------------------------- /macsmc-battery/udev/93-macsmc-battery-charge-control.rules: -------------------------------------------------------------------------------- 1 | # load stored charge_control_end_threshold 2 | SUBSYSTEM=="power_supply", KERNEL=="macsmc-battery", IMPORT{file}="/etc/udev/$kernel.conf" 3 | SUBSYSTEM=="power_supply", KERNEL=="macsmc-battery", ENV{CHARGE_CONTROL_END_THRESHOLD}=="[0-9][0-9]", GOTO="set_charge_control_end_threshold" 4 | 5 | GOTO="skip_charge_control_end_threshold" 6 | LABEL="set_charge_control_end_threshold" 7 | SUBSYSTEM=="power_supply", KERNEL=="macsmc-battery", ATTR{charge_control_end_threshold}="$env{CHARGE_CONTROL_END_THRESHOLD}" 8 | LABEL="skip_charge_control_end_threshold" 9 | 10 | # enable monitoring via a systemd path unit 11 | SUBSYSTEM=="power_supply", KERNEL=="macsmc-battery", TAG+="systemd" 12 | SUBSYSTEM=="power_supply", KERNEL=="macsmc-battery", ENV{SYSTEMD_WANTS}="macsmc-battery-charge-control-end-threshold.path" 13 | -------------------------------------------------------------------------------- /systemd/first-boot.service: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | [Unit] 4 | Description=Sets up system on first boot 5 | Before=sshd.service first-boot-complete.target 6 | Wants=first-boot-complete.target 7 | ConditionPathIsReadWrite=/etc 8 | ConditionFirstBoot=yes 9 | 10 | [Service] 11 | Type=oneshot 12 | RemainAfterExit=yes 13 | ExecStart=/usr/bin/first-boot 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /udev/hwdb.d/65-autosuspend-override-asahi-sdhci.hwdb: -------------------------------------------------------------------------------- 1 | pci:v000017A0d00009755* 2 | ID_AUTOSUSPEND=0 3 | -------------------------------------------------------------------------------- /update-grub: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | 4 | set -e 5 | 6 | [ -e /etc/default/update-grub ] && . /etc/default/update-grub 7 | 8 | if [ -e "$(dirname "$0")"/functions.sh ]; then 9 | . "$(dirname "$0")"/functions.sh 10 | else 11 | . /usr/share/asahi-scripts/functions.sh 12 | fi 13 | 14 | : ${BOOT_PART:="/boot"} 15 | : ${EFI_PART:=} 16 | : ${GRUB_DIR:="$BOOT_PART/grub"} 17 | : ${CONFIG:="$GRUB_DIR/grub.cfg"} 18 | : ${MODULES:="ext2 fat part_gpt search"} 19 | 20 | umount=false 21 | 22 | if [ -z "$EFI_PART" ] && [ -z "$TARGET" ]; then 23 | EFI_PART=/run/.boot-efi 24 | mount_boot_esp "$EFI_PART" 25 | umount=true 26 | fi 27 | 28 | : ${TARGET:="$EFI_PART/EFI/BOOT/BOOTAA64.EFI"} 29 | 30 | fs="$(grub-probe "$BOOT_PART" -t fs)" 31 | uuid="$(grub-probe "$BOOT_PART" -t fs_uuid)" 32 | part="$(grub-probe "$BOOT_PART" -t drive | sed -e 's/(.*,/hd0,/' | tr -d ')')" 33 | grub_path="$(grub-mkrelpath "$GRUB_DIR")" 34 | 35 | if [ -z "$uuid" ]; then 36 | echo "Error: Unable to determine root filesystem UUID" 37 | exit 1 38 | fi 39 | 40 | echo "Filesystem: $fs" 41 | echo "UUID: $uuid" 42 | echo "Partition: $part" 43 | echo "Relative path: $grub_path" 44 | 45 | cat > /tmp/grub-core.cfg <"$m1n1config" 31 | 32 | if [ -e "$CONFIG" ]; then 33 | info "Reading m1n1 config from $CONFIG:" 34 | while read line; do 35 | case "$line" in 36 | "") ;; 37 | \#*) ;; 38 | chosen.*=*|display=*|mitigations=*) 39 | echo "$line" >> "$m1n1config" 40 | info " Option: $line" 41 | ;; 42 | *) 43 | warn " Ignoring unknown option: $line" 44 | ;; 45 | esac 46 | done <$CONFIG 47 | fi 48 | 49 | if [ -z "$TARGET" ]; then 50 | mount_sys_esp /run/.system-efi 51 | TARGET="/run/.system-efi/m1n1/boot.bin" 52 | umount=true 53 | fi 54 | 55 | cat "$M1N1" $DTBS >"${TARGET}.new" 56 | gzip -c "$U_BOOT" >>"${TARGET}.new" 57 | cat "$m1n1config" >>"${TARGET}.new" 58 | 59 | if [ -e "$TARGET" ]; then 60 | # clobber "${TARGET}.old" only if "$TARGET" changes, use sha512sum to 61 | # avoid dependency on diffutils 62 | SHA512_CUR=$(sha512sum "$TARGET" | cut -d' ' -f1) 63 | SHA512_NEW=$(sha512sum "$TARGET.new" | cut -d' ' -f1) 64 | [ "$SHA512_CUR" != "$SHA512_NEW" ] && mv -f "$TARGET" "${TARGET}.old" 65 | fi 66 | 67 | mv -f "${TARGET}.new" "$TARGET" 68 | 69 | echo "m1n1 updated at ${TARGET}" 70 | $umount && umount /run/.system-efi 71 | true 72 | --------------------------------------------------------------------------------