Installation

The installation starts in macOS and continues in Fedora:

  1. In macOS Recovery, disable Secure Boot and allow booting from external media.
  2. In macOS, create a separate partition for Fedora.
  3. Boot macOS and run the KAIT2EN installer.
  4. Choose a supported Fedora edition and an empty USB drive.
  5. The installer downloads and verifies the official Fedora image.
  6. It collects the Apple Wi-Fi firmware from your Mac and, where required, the PCIe Bluetooth firmware.
  7. It writes the unchanged Fedora image to the USB drive, then adds separate KAIT2EN boot files for keyboard, trackpad, firmware, and installer support.
  8. Boot the USB drive and install Fedora. After the first login, the guided KAIT2EN setup installs the remaining drivers and system integration.
  9. After another reboot, you can enjoy KAIT2EN on top of vanilla Fedora.

The installer currently supports Fedora Workstation, Fedora KDE Desktop and Fedora COSMIC Spin. We strongly recommend installing Workstation (Gnome) because that is what we devs use ourselves. KDE and Cosmic are generally more problematic. We can't help you with that because we don't use it.

Before you start

You need:

  • a T2 Mac with macOS still installed
  • an empty USB drive
  • an internet connection in macOS

Back up important data before changing partitions or boot settings.

Keep macOS installed. It is the clean source for Apple firmware and can recover T2/bridgeOS hardware states.

Disable Apple Secure Boot#

  • Shut down the Mac.
  • Turn it on and immediately hold Command-R until macOS Recovery starts.
  • Select a macOS administrator account and enter its password when prompted.
  • From the menu bar, open Utilities > Startup Security Utility.
  • Select the macOS system disk if the utility asks for one.
  • Set the following options:

Secure Boot: No Security

Allowed Boot Media: Allow booting from external or removable media

  • Close Startup Security Utility and restart into macOS.

Apple Secure Boot cannot boot standard Fedora while it is enabled. The installer checks the current setting and warns when it cannot confirm that Secure Boot is disabled.

Create space for Fedora#

Open Disk Utility in macOS. Select the internal macOS disk or container, choose Partition, and add a real exFAT partition for Fedora. Do not add an APFS volume. Fedora will reformat this partition during installation; exFAT only makes it easy to identify.

Choose the size carefully because resizing the partitions later is not a small maintenance task. Keep at least 50 GB for macOS so there is enough space for updates, firmware work, and recovery tasks. Give the remaining space you want to use for Linux to the new partition.

Do not delete the EFI partition or macOS.

Create the Fedora USB drive

Boot macOS and connect the empty USB drive. Open Terminal and run:

curl -fsSL https://github.com/kaiT2en/KaiT2en-Fedora/releases/latest/download/install-kait2en-fedora.sh | bash

Choose the Fedora desktop and USB drive. The script downloads and verifies the official Fedora image, finds the Apple Wi-Fi firmware used by this Mac and asks for an exact confirmation before erasing the USB drive.

The official Fedora image itself is not modified. After writing the verified vanilla image, the script adds KAIT2EN boot files only to the USB drive's EFI partition. Separate initramfs overlays provide the temporary input drivers and installer integration at boot; Fedora's live system and installation payload remain unchanged.

Be exact when selecting the drive. All data on it will be destroyed.

Install Fedora

Shut down or reboot the Mac. Hold Option during startup and select the orange EFI Boot entry for the Fedora USB drive. The KAIT2EN Fedora entry starts automatically.

Keyboard, trackpad, and Wi-Fi should work in the live system and installer. The live system installs the Apple Wi-Fi firmware from the USB drive for itself, so you can connect to a network before or instead of installing Fedora.

Macs whose Bluetooth controller sits on PCIe (BCM4377) also get their Apple Bluetooth firmware in the live system, so a Bluetooth keyboard or mouse can be paired before installing. Every other T2 Mac drives Bluetooth over UART and needs no separate firmware file.

Install Fedora normally. Use custom partitioning and select the Linux partition you created in macOS. Do not erase the whole disk or macOS. When reinstalling, format an existing Linux /boot partition so old kernels do not fill it.

After installation finishes, remove the USB drive and boot the installed Fedora system.

If the live system does not start#

The boot menu offers a few troubleshooting entries that are only needed when the normal boot does not work. Try them in this order and stop at the first one that works:

  1. Troubleshooting: KaiT2en with boot messages shows the console instead of the logo. Photograph the last lines for a bug report.
  2. Troubleshooting: KaiT2en with the dedicated GPU disabled keeps amdgpu out of the boot and leaves the Intel GPU fully accelerated.
  3. Troubleshooting: KaiT2en with basic graphics adds nomodeset. Rendering is done in software and feels slow, but it can run the installation.
  4. Troubleshooting: KaiT2en with basic graphics and conservative PCIe is the last resort and also covers a power off coming from PCIe or Thunderbolt.

All of them keep the KAIT2EN input drivers. If entry 2 or 3 was needed, make the fix permanent afterwards as described in Configure GPUs.

If hardware is missing in the live system#

KAIT2EN supports the known T2 configurations, but Apple shipped several controller and firmware variants. If keyboard, trackpad, Wi-Fi, or PCIe Bluetooth support is missing, collect diagnostics before continuing with the installation.

The individual helpers can be run manually to see the Wi-Fi or Bluetooth setup result directly:

sudo /run/kait2en/kait2en-live-wifi
sudo /run/kait2en/kait2en-live-bluetooth

For a complete diagnostic archive, run:

sudo /run/kait2en/kait2en-live-diagnostics --rerun

This reruns the firmware setup while recording what happened. The archive lands on a second USB drive when one is mounted, otherwise in /tmp; the path is printed at the end. It contains host names, MAC addresses, and the names of nearby wireless networks, so inspect it before attaching it to a bug report.

Finish the KAIT2EN installation

Sign in to Fedora and connect to Wi-Fi. A terminal opens automatically and starts the KAIT2EN installer in two phases. Do not close this window and follow the prompts.

The first phase updates Fedora and prepares the new kernel. Reboot when asked. After signing in again, the second phase opens automatically and runs the regular KAIT2EN installer. Reboot once more after it completes successfully.

If the terminal does not appear, open one and run this command without sudo:

kait2en-install

The installer asks for administrator access when it is needed. It can also be started again at any later time to update KAIT2EN.

KAIT2EN applications

KAIT2EN includes several applications for monitoring and configuring T2 Mac hardware. The installer selects hardware-specific applications where necessary. Graphical apps show up in the app drawer after installation. T2 Journal is used from a terminal.

T2 Fan Control#

Monitors temperatures and fan speeds and provides an editable fan curve. A background service keeps automatic fan control active across login, suspend, resume, and reboot. It also features an adjustable "system-chill wall" that sets the fans to 100% to prevent case heating and in effect prochot.

T2 SMC Control#

Displays SMC temperatures, fan speeds, power data, and the hardware clock, and can write the current system time to that clock. The battery charge limit is shown but not set here: t2smc exposes it as the standard charge_control_end_threshold, so the desktop environment offers it in its own power settings. Note that this data shown in this app is direct hardware readings. It is the single source of truth for temperatures and battery statistics. Desktop environment's readings of battery charge are only estimations. As we promised to ship a vanilla Fedora with KaiT2en sugar on top, we did not manipulate it to show SMC values in Gnome/Plasma. This will later be solved when upstreaming SMC.

T2 CPU Control#

Shows CPU frequency, temperature, package power, and throttling state. It can configure PL1/PL2 power limits, Turbo Boost, maximum frequency, and the CPU thermal target, and includes an automatic power-limit benchmark. It serves the purpose of preventing prochot on T2 Macbooks.

T2 Power Explorer#

Presents the kernel device hierarchy together with runtime power-management state and diagnostics. It helps identify devices that remain active and keep the system from reaching deeper power-saving states.

T2 Journal#

Fetches Apple T2 bridgeOS logs over the internal Apple T2 Bridge network link and merges them chronologically with the Linux journal. It can select one boot or all retained boots, filter by regular expression or source, and emit text or JSONL. The first query downloads a BridgeOS snapshot automatically; use t2journal refresh to replace it explicitly.

The link is set up by the installer and managed by kait2en-t2-remote, the same service that holds the T2 video encoder open. It is disconnected before suspend and reconnected after resume, so there is nothing to configure.

Typical queries are:

t2journal -b
t2journal -b -1 --grep 'suspend|watchdog'
t2journal --allboots --source t2
t2journal -b --output jsonl > merged.jsonl

t2journal refresh --sysdiagnose additionally keeps a copy of the downloaded sysdiagnose archive in the current directory, e.g. to extract panic logs from it yourself.

Run t2journal --help for all filtering and refresh options.

T2 Power Tune#

Scans for available PCIe ASPM, runtime power-management, wakeup, LTR, and other power-saving tunables. Selected changes can be tested temporarily or installed as a persistent systemd service. Replaces powertop/tlp for reaching deeper (pkg) c-states.

T2 Force Click#

Configures the Force Touch trackpad's normal-click pressure and its harder Force Click threshold. Force Click is available as a separate event, so it can be bound without changing normal clicks, tap-to-click, scrolling, or gestures. Those remain libinput's job.

One action can be selected for a Force Click. Alternating copy/paste, a recorded keyboard shortcut, or an advanced shell command. A physical three-finger click already produces a middle click directly from the trackpad, so it does not need a Force Click binding. Commands run as the active desktop user.

KAIT2EN Touch Bar#

Optional. The installer asks at the very beginning whether to install it. Without it, Apple's native firmware row (esc, brightness, volume and media keys, F-keys while Fn is held) keeps working. Remove it again with sudo ./apps/t2-touchbar/uninstall.sh. That restores the native row and keeps personal settings and learned state.

Keeps the Touch Bar black until it is touched or Fn is pressed. The waking touch is consumed, preventing accidental activation of an invisible key. A short Fn press opens the remembered media or function-key row; holding Fn for 600 milliseconds, or swiping across the lit bar with two fingers, switches that remembered row. Swiping with two fingers across the dark bar changes the volume without waking it.

The initial five-second timeout is learned independently for both rows. It can grow to thirty seconds after a quick wake-and-use continuation, and shrinks slowly when the extra time repeatedly goes unused. Touch ID always replaces the row with the fingerprint prompt during sudo and lock-screen authentication. Accepted key presses produce a light impulse through the trackpad actuator.

While dark, the separate 05ac:8102 brightness controller may runtime-suspend. The 05ac:8302 display/touch device deliberately remains awake so the first touch can still wake the row.

The installer switches that device from Apple's firmware row to the DRM display through a root system service. Reboot once after the first install so the desktop's user-systemd manager receives the new device-access group; a logout alone may leave that manager running. Until then, the installer falls back to the firmware row instead of leaving a black panel.

Use kait2en-touchbar --status to inspect learned state and kait2en-touchbar --reset-learning to return it to five seconds. System defaults are in /etc/kait2en/touchbar.toml; a user can override the complete file at $XDG_CONFIG_HOME/kait2en-touchbar/config.toml. key_color sets the glyph color as #rrggbb; the default cool white matches the keyboard backlight.

T2 GPU Control#

Used on supported MacBook Pro models with Intel and AMD graphics. It selects the primary GPU for the next boot and can power down the unused discrete GPU or enable AMDGPU's power-saving profile.

T2 Hybrid GPU Control#

Used on the MacBookPro15,1, MacBookPro16,1 and MacBookPro16,4. It enables an iGPU-driven desktop with PRIME offload to the AMD GPU, which wakes on demand and returns to D3cold when idle. Suspend and resume work in this mode. A discrete-GPU boot mode remains available as a recovery option.

T2 Kernel Builder#

Provides a graphical workflow for building customized Fedora kernels with the required T2 configuration and selected patch groups. Completed builds can be installed or removed through restricted privileged helpers.

Audio DSP

This page explains the audio DSP support that KAIT2EN installs automatically. It is not an installation guide. All profiles are installed together. Supported Macs select the matching profile at runtime. Unsupported models continue to use the native T2 audio devices.

DSP in general#

The T2 audio driver exposes the physical speaker channels, but the T2 does not apply the model-specific processing to audio coming from the host; macOS does that on the host as well. KAIT2EN provides that processing as a PipeWire filter graph per model.

Depending on the model, the graph

  • distributes stereo audio across the physical woofer and tweeter channels
  • applies the model's equalization and crossovers as biquad filters
  • applies a multiband compressor and limiters
  • widens the stereo image with crosstalk cancellation
  • adds virtual-bass processing

The biquad chains are cheap compared with the FIR convolution used before.

On supported Macs, the resulting output appears as DSP Speakers device. The unprocessed Apple Internal Speakers device remains available for comparison and diagnostics. Headphones do not pass through the speaker DSP graph.

Supported models#

Model DSP profile
MacBook Air 2018 MacBookAir8,1
MacBook Air 2019 MacBookAir8,2
MacBook Air 2020 (Intel) MacBookAir9,1
MacBook Pro 15-inch 2018/2019 MacBookPro15,1
MacBook Pro 13-inch 2018/2019, four Thunderbolt ports MacBookPro15,2
MacBook Pro 15-inch 2018/2019, Radeon Pro Vega MacBookPro15,3
MacBook Pro 13-inch 2019, two Thunderbolt ports MacBookPro15,4
MacBook Pro 16-inch 2019 MacBookPro16,1
MacBook Pro 13-inch 2020, four Thunderbolt ports MacBookPro16,2
MacBook Pro 13-inch 2020, two Thunderbolt ports MacBookPro16,3
MacBook Pro 16-inch 2019 MacBookPro16,4
iMac 27-inch 2020 iMac20,1
iMac Pro 2017 iMacPro1,1

udev identifies the model from DMI and assigns a short ALSA card ID. WirePlumber uses that ID and the UCM Speaker/Mic node to select a graph. There is no install-time PCI-address substitution. KAIT2EN does not reuse a profile on an unlisted model. Reboot after installing or removing t2-dsp.

Automatic selection#

The WirePlumber software-DSP integration gives the DSP sink a higher session priority than the underlying speaker sink. WirePlumber should therefore select the DSP output automatically when the profile is first created.

Profile origins and support#

The speaker and microphone graphs are KAIT2EN's own work and are generated per model. The license information lives under dsp/ in the repository and is shipped in /usr/share/licenses/t2-dsp/ with the package.

Thanks to lemmyg for the pioneering work: the first PipeWire DSP graphs for T2 Macs were his, and they were the template KAIT2EN's audio DSP started from.

Problems with these profiles must be reported to the KAIT2EN issue tracker, not to lemmyg's project: the current graphs, routing and UCM integration are maintained here.

Check the active output#

The sound settings should show the model-specific DSP output on a supported Mac. PipeWire can also list it directly:

wpctl status

The active sink is marked with an asterisk. If the DSP device is missing after the regular installation and a reboot, include the model identifier and this output in a KAIT2EN issue:

cat /sys/class/dmi/id/product_name
wpctl status
journalctl --user -b -u wireplumber -u pipewire -u pipewire-pulse

Configure GPUs

If a Mac has a dGPU, it will use it for boot and it will also use it as primary display adapter by default. An iMac is no exception in that aspect, but it is not able to switch between internal and dedicated GPU because the display lines from iGPU to display are missing. So on iMacs, the iGPU is only used for offloading. Thus, if you are an iMac user, this guide is not for you. Same for Mac Pro users, since Mac Pros have no iGPU. This guide is only for Macbook Pro users.

MacBookPro15,1, MacBookPro16,1 and MacBookPro16,4: enable hybrid graphics#

KaiT2en installs T2 Hybrid GPU Control on the MacBookPro15,1, MacBookPro16,1 and MacBookPro16,4. Open it from the application menu and enable Hybrid graphics, then reboot.

Hybrid graphics makes the integrated GPU the display GPU. Applications can still use the AMD GPU through PRIME offload. The kernel wakes it automatically for accelerated work and returns it to D3cold when it becomes idle. This keeps the dGPU available without paying its idle power cost. System suspend and resume are fully supported in hybrid mode on all three models.

The installer builds the required AMDGPU module for the current Fedora kernel. The app reports whether the required runtime-PM support is active.

This module is not managed by DKMS. After Fedora installs a new kernel, first reboot into that kernel and then rebuild its hybrid-graphics module:

cd /usr/local/src/KaiT2en-Fedora
sudo ./scripts/fedora/install-gpu-runtime-pm.sh
sudo reboot

Running the script before booting the new kernel only rebuilds the module for the old, currently running kernel. Until the rebuild and second reboot are complete, hybrid runtime PM is not available on the new kernel.

The discrete-GPU boot option remains available as a recovery setting. Rebooting is always a separate action so changing the stored boot GPU does not restart the system unexpectedly.

Other MacBooks with dGPU#

Other Intel/AMD MacBook Pro models use T2 GPU Control. Hybrid runtime PM is not enabled on those models because their dGPU power-on path is not yet reliable. T2 GPU Control has options to switch between iGPU and dGPU and to enable power saving for the dGPU. For the changes to take effect you need to reboot. Usually, users prefer iGPU as primary to save some energy and make suspend more reliable.

Hardware video decoding

Fedora's GPU drivers do not expose hardware decoding for codecs such as H.264 and H.265. This affects both AMD GPUs and Intel iGPUs. Browsers and media players can therefore fall back to CPU decoding even though the GPU contains a supported video decoder.

T2 Macs do not provide AV1 hardware decoding. YouTube should use H.264 or a hardware-supported VP9 profile to avoid unnecessary CPU load.

This page is about decoding on the GPUs. HEVC encoding runs on the T2 itself, see Hardware video encoding.

Install the VA-API drivers#

Run the installer from the KAIT2EN repository:

cd /usr/local/src/KaiT2en-Fedora
sudo bash ./scripts/fedora/install-hardware-video-decoding.sh

The script enables RPM Fusion, installs the appropriate VA-API drivers for every detected Intel and AMD GPU, and checks each render node. Review the final output: H.264 and VP9 decoding and encoding are reported as available or missing for each GPU.

No general system upgrade is performed. Browser configuration is still required as described below.

Brave and YouTube#

Open Brave's system settings and enable Use graphics acceleration when available, then restart Brave.

YouTube normally chooses between H.264, VP9 and AV1 based on the capabilities reported by the browser. T2 Macs cannot decode AV1 in hardware. To force YouTube to request H.264 in Brave, install h264ify from the Chrome Web Store. This does not interfere with Brave Shields or its ad blocking.

H.264 streams on YouTube are commonly limited to 1080p. Disable the extension when a higher resolution is more important than lower CPU use.

Start a YouTube video, right-click it and open Stats for nerds. The codec field identifies the selected stream:

  • avc1 is H.264.
  • vp09 is VP9.
  • av01 is AV1.

For the forced H.264 configuration, the field must start with avc1.

Open brave://gpu and check that Video Decode reports hardware acceleration. For the active playback session, brave://media-internals provides the more useful per-stream decoder details.

Firefox and YouTube#

In Firefox settings, leave hardware acceleration enabled. Open about:config, set the following preference to false, and restart Firefox:

media.av1.enabled

This disables AV1 but still allows YouTube to select VP9. To force H.264, install enhanced-h264ify from Mozilla Add-ons and block VP9 and AV1 while leaving H.264 enabled.

Use YouTube's Stats for nerds as described above. Firefox also reports its decoder support under about:support in the codec and media sections.

Test outside the browser#

MPV can confirm that VA-API works independently of browser configuration:

mpv --no-config \
    --hwdec=vaapi-copy \
    --hwdec-codecs=all \
    --vaapi-device=/dev/dri/renderD128 \
    --term-playing-msg='Hardware decoder: ${hwdec-current}' \
    /path/to/video.mp4

Replace the render node and video path as required. A hardware-decoded stream reports vaapi-copy instead of no.

Hardware video encoding

The T2 contains Apple's video encoder, the AVE. KAIT2EN exposes it to Linux as a standard V4L2 memory-to-memory encoder, so ffmpeg, HandBrake and anything else that speaks V4L2 can hand it raw frames and receive HEVC. The Intel and AMD GPUs keep doing the decoding; the T2 only encodes.

  • HEVC (H.265) only. There is no H.264 output.
  • Main profile from 8-bit NV12 input, Main 10 from P010 input.
  • Frame sizes from 128x128 up to 4096x2304.
  • One encode at a time. A second session is refused with EBUSY until the first has finished.

ffmpeg#

Fedora's ffmpeg-free already ships the V4L2 encoder wrapper. The encoder expects NV12 frames, so tell ffmpeg to convert:

ffmpeg -i input.mp4 -pix_fmt nv12 -c:v hevc_v4l2m2m -b:v 8M -c:a copy output.mp4

-b:v sets the target bitrate and -g the keyframe interval; -profile:v and -level are passed through as well. Without -pix_fmt nv12 ffmpeg stops with Encoder requires nv12 pixel format.

Fedora's ffmpeg does not know P010 on V4L2 devices, so 10-bit output is not available from the command line. Use the HandBrake build for Main 10.

HandBrake with T2 AVE Support#

The t2-ave branch of our HandBrake fork adds the encoder as H.265 (Apple T2 AVE) and teaches its bundled ffmpeg the 10-bit input format. Choose the main10 profile for 10-bit output.

Install our Handbrake fork with

sudo dnf install git gcc gcc-c++ make autoconf automake libtool pkgconf-pkg-config meson ninja-build nasm cmake cargo cargo-c patch tar python3 bzip2-devel xz-devel zlib-devel numactl-devel gtk4-devel glib2-devel libxml2-devel lame-devel opus-devel speex-devel libvpx-devel libass-devel libogg-devel libvorbis-devel libtheora-devel x264-devel jansson-devel libjpeg-turbo-devel gettext-devel desktop-file-utils
git clone --branch t2-ave https://github.com/deqrocks/HandBrake.git
cd HandBrake && ./configure --launch-jobs="$(nproc)" --launch
sudo make -C build install

Touch ID

KAIT2EN lets the finger you enrolled under macOS unlock the login screen and confirm sudo on Linux. Nothing is enrolled on Linux: the Secure Enclave keeps the fingerprint, compares it, and Linux only receives its verdict.

Prerequisites#

You need a finger enrolled under macOS, in System Settings > Touch ID. The macOS installer tells you if none is enrolled while you are still in macOS. Your macOS and Linux passwords do not have to match.

The Secure Enclave also needs a password to have unlocked its biometric keybag once since the T2 itself last powered on. Rebooting the Mac does not power off the T2, it only sleeps bridgeOS, so log into macOS once and it stays unlocked across Linux reboots. If journalctl -u kait2en-t2-touchid says no macOS user has a finger enrolled despite one clearly being set up, this is why.

TLDR: TouchID is bound to T2 powercycles. Once the T2 panics or power is cut off, it will reboot and it will disable TouchID until you reboot into macOS and enter your password at login.

Binding#

The Secure Enclave keeps the fingerprint and compares it. Linux only learns which enrolled finger it saw, and fprintd remembers which of them belong to your account. That binding is made without touching the sensor, because it is only the statement that the macOS-enrolled fingers are yours, the same assumption macOS itself makes. The finger still has to be on the sensor at every login.

fprintd-list $USER shows the bound fingers. The sensor does not say which finger a template is, so the labels are positional: the first is right-index-finger, the second right-middle-finger, and so on. Fingers enrolled under macOS later are bound the next time the bridge starts, for example after a reboot.

Several users#

The bridge looks for the macOS user that has fingers enrolled by itself and binds them to the Linux account that ran the installer. If that is not the right pairing, edit /etc/kait2en/t2-touchid.conf: T2_TOUCHID_UID is the macOS id (id -u under macOS, usually 501 or 502) and T2_TOUCHID_BIND_USER the Linux account. Restart kait2en-t2-touchid afterwards. Any other Linux user can bind a finger by hand with fprintd-enroll and a touch.

Turning it off#

sudo authselect disable-feature with-fingerprint
sudo systemctl disable --now kait2en-t2-touchid

Updating

KAIT2EN is meant to disappear. It's part of the concept. It serves the purpose of upstreaming code fixes. Every module and fix that gets upstreamed will disappear from the repo. Until we are left with a few T2 specific apps and other things that can't be upstreamed. Maybe it will survive as a collection of helpful apps for T2 Macs.

As long as this isn't the case, we need to update the Fedora kernel and our modules and apps. The question how to do that has kept us a bit busy. We could go COPR and offer .rpm. But the project is yet too small to fund itself.

Updating KAIT2EN#

Open a terminal and run:

kait2en-install

This updates the KAIT2EN Git checkout and runs the regular project installer. Review its output and reboot after it completes successfully.

Updating Fedora#

You just update Fedora like everyone else. DKMS will notice and recompile our modules against the latest kernel. It's always worth visiting the KAIT2EN community on Discord or Matrix to make sure you won't run into issues like kernel regressions.

So you messed up?#

You can mess up DKMS when upgrading the kernel. For example when interrupting DKMS while the new Kernel is booting. Then you are left with half broken KAIT2EN modules. To repair this, just boot into an older kernel and clean up the new.

#replace the kernel version 7.1.3-201.fc44.x86_64 with your own
sudo dracut --force /boot/initramfs-7.1.3-201.fc44.x86_64.img 7.1.3-201.fc44.x86_64 
sudo kernel-install add 7.1.3-201.fc44.x86_64 /lib/modules/7.1.3-201.fc44.x86_64/vmlinuz
sudo grubby --set-default /boot/vmlinuz-7.1.3-201.fc44.x86_64

When you can't boot at all#

If you can no longer boot your system or the input drivers are not loaded, use the KAIT2EN USB stick. Boot into a live desktop and run:

sudo kait2en-rescue

The rescue tool finds and mounts your Fedora installation, chroots you into it, and lets you rebuild the initramfs, verify the T2 input drivers, or choose the default boot entry.

Murphy's law: We WILL mess up!#

We are humans. We will mess up at some point. We recommend not to update when you don't have an external keyboard/mouse around. Like when you are travelling. But you should always be able to use GRUB to boot into an older kernel anyways. But be warned that when we mess up, you could loose VHCI devices or WiFi. And remember we are not paid. We will waste your time and we don't accept complaints.

Installed files

KAIT2EN keeps Fedora's vanilla kernel and installs T2 hardware support as a separate layer. The changes we are doing to your system are documented here to provide transparency to users and devs.

Repo location and updater#

The guided installer creates a clean checkout of the main branch at:

/usr/local/src/KaiT2en-Fedora

kait2en-install fast-forwards this checkout and runs scripts/fedora/install.sh. It refuses to overwrite local changes or use a checkout with an unexpected Git remote. Its persistent files are:

/usr/local/bin/kait2en-install
/var/lib/kait2en-installer/state
~/.local/state/kait2en/install.log

Kernel modules#

The installer copies each DKMS source package to /usr/src/<name>-<version>/, registers it and builds it for the running Fedora kernel. DKMS keeps its build state below /var/lib/dkms/ and rebuilds the modules for later kernel updates. modinfo -n <module> prints the installed kernel object path.

DKMS source Installed module Purpose
t2bce_stack t2bce_dma Shared DMA queue engine for T2 BCE clients
t2bce_stack t2bce_core T2 bridge PCI device, mailbox, power management and transport
t2bce_stack t2bce_vhci Virtual USB host for internal T2 input devices
t2bce_stack t2bce_audio Apple T2 audio driver
t2bce_stack t2bce_ave Apple T2 AVE HEVC encoder
t2smc t2smc Fan, temperature, charge-limit and RTC access through hwmon
t2bdrm t2bdrm Touch Bar DRM display device
t2touchbar t2hid, t2touchbar_bl, t2touchbar_kbd Internal HID quirks, Touch Bar backlight and keyboard mode
hid_t2magicmouse hid_t2magicmouse Internal trackpad support with the required Asahi patches
t2_precision_trackpad t2_precision_trackpad Force Touch trackpad driver with dynamic surface geometry and a separate Force Click event
t2_trackpad_actuator t2_trackpad_actuator T2 Force Touch actuator transport
t2mfi_fastcharge t2mfi_fastcharge Fast-charge control for Apple MFi devices
t2gmux t2gmux GMUX handling on dual-GPU Macs
t2thunderbolt t2thunderbolt Thunderbolt power-management ordering and T2 PCI quirks
t2smp t2smp Defers secondary CPU hotplug to avoid firmware-sensitive resume delays

The installer also writes /etc/kernel/install.d/39-kait2en-dkms-cleanup.install. The hook removes stale DKMS build state before a kernel installation is retried.

On the MacBookPro15,1, MacBookPro16,1 and MacBookPro16,4, the app installer also builds the AMDGPU module with the hybrid runtime-PM patches and installs it for the running kernel at:

/usr/lib/modules/<kernel>/updates/kait2en-gpu-runtime-pm/amdgpu.ko.xz

The corresponding modprobe configuration is installed as /usr/lib/modprobe.d/kait2en-gpu-runtime-pm.conf.

Unlike the T2 modules above, this patched AMDGPU module is not built by DKMS. After a Fedora kernel update, boot the new kernel before rebuilding it for its exact release:

cd /usr/local/src/KaiT2en-Fedora
sudo ./scripts/fedora/install-gpu-runtime-pm.sh
sudo reboot

The script installs the module for the running kernel and rebuilds that kernel's initramfs.

Kernel arguments#

install-kernel-args.sh updates every installed kernel entry with grubby --update-kernel=ALL. Inspect the effective arguments with:

grubby --info=DEFAULT

KAIT2EN adds these arguments to every installed kernel through grubby:

intel_iommu=on
iommu=pt
pm_async=off
brcmfmac.p2pon=0
pcie_aspm=force
pcie_aspm.policy=powersave
pcie_ports=native
pci=noaer
mem_sleep_default=deep
initcall_blacklist=cmos_init,magicmouse_driver_init
module_blacklist=acpi_tad,applesmc,macsmc,hid_apple,hid_appletb_bl,hid_appletb_kbd,hid_magicmouse,appletbdrm,apple_bce,apple_mfi_fastcharge,apple_gmux

On every T2 Mac, the installer enables HuC firmware loading for the Intel GPU:

i915.enable_guc=2

The value is a bitmask: 2 selects. HuC is used by Intel media workloads, including HEVC operations.

KAIT2EN does not install a custom kernel or a separate GRUB configuration file.

Audio configuration#

The ALSA UCM profiles define the T2 speaker, microphone and headset paths:

/usr/share/alsa/ucm2/AppleT2/HiFi-x2.conf
/usr/share/alsa/ucm2/AppleT2/HiFi-x4.conf
/usr/share/alsa/ucm2/AppleT2/HiFi-x6.conf
/usr/share/alsa/ucm2/conf.d/AppleT2x2/AppleT2x2.conf
/usr/share/alsa/ucm2/conf.d/AppleT2x4/AppleT2x4.conf
/usr/share/alsa/ucm2/conf.d/AppleT2x6/AppleT2x6.conf

The installer and the independent t2-dsp package deploy all model-specific graphs and FIR data. udev and WirePlumber select the matching profile at runtime.

/usr/share/t2-dsp/profiles/<profile>/
/usr/share/wireplumber/wireplumber.conf.d/51-t2-dsp.conf
/usr/share/wireplumber/scripts/t2-default-output.lua
/usr/share/pipewire/pipewire.conf.d/50-kait2en-quantum.conf
/usr/lib/udev/rules.d/89-t2-dsp.rules
/usr/libexec/t2-dsp/package-actions
/usr/share/licenses/t2-dsp/

Unlisted models receive no DSP graph at runtime. Former generated /etc fragments are backed up under /var/lib/kait2en/migration/t2-dsp/ with ownership receipts under /var/lib/kait2en/ownership/. Removal cleans verified backups. Migration errors are collected in /var/log/t2-dsp-install.log and the installer summary. See Audio DSP for the supported-model table, audio behavior and diagnostics.

System configuration and services#

Path Purpose
/etc/systemd/system/kait2en-suspend.service Calls the suspend helper before sleep.target and again after resume
/usr/local/libexec/kait2en/kait2en-suspend.sh Handles the BCM4377 suspend workaround described below
/etc/systemd/system/t2-services-suspend.service Runs feature sleep/resume hooks around sleep
/usr/local/libexec/t2-services/t2-ncm-sleep Runs installed feature hooks before sleep and after resume
/usr/local/libexec/t2-services/sleep.d/t2-ave Closes/reopens sessions only when the AVE daemon is running
/etc/systemd/system/kait2en-t2-remote.service Loads t2bce_ave and runs t2remote, which holds the bridgeOS services Linux uses, currently com.apple.aveservice for the video encoder
/usr/local/bin/t2remote RemoteXPC service manager; t2remote status shows the live services. Listens on /run/t2remote.sock
NetworkManager profile Apple T2 Bridge IPv6 link-local connection to the T2 over its internal CDC-NCM interface, bound to the interface's MAC address. Replaces the earlier t2_ncm udev rule
/etc/modprobe.d/kait2en-silent-blacklist.conf Silently ignores attempts to load drivers replaced by KAIT2EN modules
/usr/share/plymouth/themes/kait2en/ macOS-style boot splash with a KAIT2EN logo
/usr/share/pixmaps/kait2en-gdm-logo.png White and red KAIT2EN logo shown by GDM
/etc/dconf/db/gdm.d/00-kait2en Configures the GDM logo and solid black login background
/usr/share/backgrounds/kait2en/gdm-black.png Black GDM background image
/usr/share/gnome-shell/gnome-shell-theme.gresource GNOME Shell theme patched so the GDM and lock-screen shield render black
/etc/dracut.conf.d/90-kait2en-input.conf Keeps the internal keyboard drivers in initramfs images built during kernel updates
/boot/initramfs-<running-kernel>.img Rebuilt by Dracut after modules and ACPI handling are complete

kait2en-suspend.service is enabled on every installation. Before suspend, it checks for a Broadcom PCI device with vendor ID 0x14e4 and device ID 0x5f69, 0x5f71, 0x5f72 or 0x5fa0. If one is present, it unloads brcmfmac_wcc, brcmfmac and hci_bcm4377 in that order. After resume it loads brcmfmac and brcmfmac_wcc, waits five seconds, then loads hci_bcm4377.

If the controller is absent, the service logs that the fix is not needed and does not unload a module. State files for modules successfully unloaded by the helper exist only until resume below /run/kait2en-suspend/.

The installer checks the running kernel log for two known Apple ACPI firmware errors. It only deploys an override when the error is present and the generated table passes validation with iasl:

/usr/local/lib/firmware/acpi/*.aml
/usr/local/lib/firmware/acpi/.kait2en-*.sha256
/etc/dracut.conf.d/t2-acpi-fix.conf
/var/backups/t2-acpi-fix/<timestamp>/

The backup contains every managed file that existed before deployment and a manifest. KAIT2EN only replaces or removes an ACPI table when its ownership marker contains the table's current SHA-256 checksum. Existing unmarked tables and modified managed tables are left unchanged and reported as conflicts.

Apple firmware from the installer USB drive#

The guided installer copies Apple's own firmware for this Mac from the USB drive into the installed system, renamed to the file names the Linux drivers ask for:

/usr/lib/firmware/brcm/brcmfmac<chip>-pcie.apple,<board>*

Macs with the BCM4377 PCIe Bluetooth controller (14e4:5fa0) additionally get the two Bluetooth blobs. Every other T2 Mac drives Bluetooth over UART and gets nothing here:

/usr/lib/firmware/brcm/brcmbt<chip><stepping>-apple,<board>[-<vendor>].bin
/usr/lib/firmware/brcm/brcmbt<chip><stepping>-apple,<board>[-<vendor>].ptb

The exact names are taken from what the driver asked for in the kernel log. The outcome of the Bluetooth step is recorded in the installed system at:

/var/log/kait2en/bluetooth-firmware.log

Applications#

t2-fan-control, t2-smc-control, t2-power-explorer, t2-cpu-control, t2-journal, kait2en-touchbar, kernel-builder, and t2-power-tune are installed system-wide under /usr/local. kait2en-touchbar is optional and only installed when selected at the start of the installation.

MacBookPro15,1, MacBookPro16,1 and MacBookPro16,4 get t2-hybrid-gpu-control; other MacBook Pro models with Intel and AMD display devices get t2-dgpu-control. All KAIT2EN desktop applications use the shared header wordmark at /usr/local/share/kait2en/kait2en-wordmark.png.

Application Installed files
T2 Fan Control /usr/local/bin/t2-fancontrol-gtk, /usr/local/share/applications/org.t2fancontrol.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2fancontrol.gtk.svg, /usr/local/lib/systemd/system/t2-fancontrol.service
T2 SMC Control /usr/local/bin/t2-smc-control, /usr/local/share/applications/org.t2smccontrol.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2smccontrol.gtk.svg
T2 Power Explorer /usr/local/bin/t2-power-explorer, /usr/local/libexec/t2-power-explorer-status, /usr/local/share/applications/org.t2powerexplorer.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2powerexplorer.gtk.svg, /usr/share/polkit-1/actions/org.t2powerexplorer.policy
T2 Journal /usr/local/bin/t2journal
T2 CPU Control /usr/local/bin/t2-cpu-control, /usr/local/libexec/t2-cpu-control-helper, /usr/local/libexec/t2-cpu-control-status, /usr/local/libexec/t2-cpu-kernel-benchmark, /usr/local/lib/systemd/system/t2-cpu-control.service, /usr/local/lib/systemd/system-sleep/t2-cpu-control, /usr/local/share/applications/org.t2cpucontrol.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2cpucontrol.gtk.svg, /usr/share/polkit-1/actions/org.t2cpucontrol.policy
T2 Kernel Builder /usr/local/bin/t2-kernel-builder, /usr/local/libexec/t2-kernel-builder-cleanup, /usr/local/libexec/t2-kernel-builder/build.sh, /usr/local/libexec/t2-kernel-builder/configs/*.config, /usr/local/share/applications/org.t2kernelbuilder.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2kernelbuilder.gtk.svg, /usr/local/share/polkit-1/actions/org.t2kernelbuilder.gtk.policy
T2 Power Tune /usr/local/bin/t2-power-tune, /usr/local/libexec/t2-power-tune-helper, /usr/local/libexec/t2-power-tune-status, /usr/local/share/applications/org.t2powertune.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2powertune.gtk.svg, /usr/share/polkit-1/actions/org.t2powertune.policy
T2 Force Click /usr/local/bin/t2-force-click, /usr/local/share/applications/org.t2forceclick.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2forceclick.gtk.svg, /usr/local/lib/systemd/system/t2-force-click.service
KAIT2EN Touch Bar /usr/local/bin/kait2en-touchbar, /usr/local/lib/systemd/user/kait2en-touchbar.service, /usr/local/lib/systemd/system/kait2en-touchbar-attach.service, /usr/local/lib/udev/rules.d/99-zz-kait2en-touchbar.rules, /etc/kait2en/touchbar.toml, /usr/local/share/licenses/kait2en-touchbar/THIRD-PARTY-NOTICES.md
T2 Hybrid GPU Control /usr/local/bin/t2-hybrid-gpu-control, /usr/local/libexec/t2-hybrid-gpu-control-helper, /usr/local/libexec/t2-hybrid-gpu-control-status, /usr/local/share/applications/org.t2hybridgpucontrol.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2hybridgpucontrol.gtk.svg, /usr/share/polkit-1/actions/org.t2hybridgpucontrol.gtk.policy, /usr/share/polkit-1/actions/org.t2hybridgpucontrol.gtk.status.policy
T2 GPU Control /usr/local/bin/t2-dgpu-control, /usr/local/libexec/t2-dgpu-control-helper, /usr/local/libexec/t2-dgpu-control-status, /usr/local/share/applications/org.t2dgpucontrol.gtk.desktop, /usr/local/share/icons/hicolor/scalable/apps/org.t2dgpucontrol.gtk.svg, /usr/local/lib/systemd/system/kait2en-dgpu-off.service, /usr/local/lib/systemd/system/kait2en-dgpu-suspend.service, /usr/local/lib/systemd/system/kait2en-amdgpu-profile.service, /usr/local/lib/systemd/system/kait2en-amdgpu-profile-resume.service, /usr/share/polkit-1/actions/org.t2dgpucontrol.gtk.policy, /usr/share/polkit-1/actions/org.t2dgpucontrol.gtk.status.policy

T2 Fan Control's service starts immediately and persists fan curves across boot and resume. T2 Hybrid GPU Control does not install system services. T2 GPU Control enables its units only when the corresponding options are applied in the app. Both privileged helpers validate the GPU layout and accept only the fixed operations exposed by their UI.

T2 Force Click persists its settings at /etc/t2-force-click/config.txt; its root daemon listens at /run/t2-force-click/daemon.sock, which is runtime state and disappears at shutdown. While the driver is loaded, its user-facing controls are:

/sys/module/t2_precision_trackpad/parameters/click_strength
/sys/module/t2_precision_trackpad/parameters/force_click_threshold_percent
/sys/module/t2_precision_trackpad/parameters/force_click_enabled

T2 trackpad actuator playback#

t2_trackpad_actuator exposes the DTrace-captured Taptic Engine click waveforms to privileged local software. A third-party helper can play the light or firm impulse by writing one of these values:

printf light | sudo tee /sys/module/t2_trackpad_actuator/parameters/play
printf firm | sudo tee /sys/module/t2_trackpad_actuator/parameters/play

The interface accepts no raw waveform bytes. light and firm select the captured reports used by the precision trackpad driver. Callers should trigger individual application events and rate-limit repeated playback themselves. The parameter is write-only and requires the module to be loaded and bound to the T2 actuator interface.

T2 Power Tune reads package C-state residency and exposes PCIe ASPM, runtime power management, LTR ignore, and additional power tunables. The optional /etc/systemd/system/kait2en-power-tune.service is created by the app only when the user chooses persistent settings. Its runtime selection cache is stored at /run/t2-power-tune/items.json and disappears on reboot.

T2 Journal stores the last successfully parsed BridgeOS log snapshot and a cache of recently discovered RemoteXPC ports for each desktop user:

~/.local/state/t2-journal/bridgeos.jsonl
~/.local/state/t2-journal/remote-ports

$XDG_STATE_HOME replaces ~/.local/state when it is set. The snapshot is created on the first query or explicit refresh and is atomically replaced only after a successful download and parse. See T2 Journal for the required network setup.

T2 Kernel Builder keeps downloaded sources, build trees and completed-build markers below $XDG_CACHE_HOME/t2-kernel-builder/build (normally ~/.cache/t2-kernel-builder/build) and its saved UI state below $XDG_CONFIG_HOME/t2-kernel-builder (normally ~/.config/t2-kernel-builder). Kernels installed through the app add their normal files below /boot and /lib/modules/<kernel>/; package-managed builds are installed through DNF.