Skip to content

Commit

Permalink
peripheral-firmware: extract on boot by default
Browse files Browse the repository at this point in the history
This improves the situation for flake users, as previously they had to
either add the non-redistributable firmware to their repositories or go
without the firmware.

This change also brings the ISO into line with the regular NixOS modules
as storing the peripheral firmware in the Nix Store is no longer a
requirement.
  • Loading branch information
Enzime committed Aug 22, 2023
1 parent 5e5a093 commit 488feab
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 62 deletions.
79 changes: 53 additions & 26 deletions apple-silicon-support/modules/peripheral-firmware/default.nix
Original file line number Diff line number Diff line change
@@ -1,44 +1,71 @@
{ config, pkgs, lib, ... }:
{
config = {
assertions = lib.mkIf config.hardware.asahi.extractPeripheralFirmware [
{ assertion = config.hardware.asahi.peripheralFirmwareDirectory != null;
imports = [
(lib.mkRemovedOptionModule [ "hardware" "asahi" "extractPeripheralFirmware" ] "This option is no longer necessary as the peripheral firmware will be extracted every boot automatically.")
];

config = let
inherit (lib) mkIf;
cfg = config.hardware.asahi;
pkgs' = cfg.pkgs;
in {
assertions = mkIf cfg.usePeripheralFirmwareFromNixStore [
{ assertion = cfg.peripheralFirmwareDirectory != null;
message = ''
Asahi peripheral firmware extraction is enabled but the firmware
location appears incorrect.
Managing the peripheral firmware in the Nix Store is enabled
but the firmware location appears incorrect.
'';
}
];

hardware.firmware = let
pkgs' = config.hardware.asahi.pkgs;
in
lib.mkIf ((config.hardware.asahi.peripheralFirmwareDirectory != null)
&& config.hardware.asahi.extractPeripheralFirmware) [
(pkgs.stdenv.mkDerivation {
name = "asahi-peripheral-firmware";
hardware.firmware = mkIf (cfg.peripheralFirmwareDirectory != null && cfg.usePeripheralFirmwareFromNixStore) [
(pkgs.stdenv.mkDerivation {
name = "asahi-peripheral-firmware";

nativeBuildInputs = [ pkgs'.asahi-fwextract pkgs.cpio ];

buildCommand = ''
mkdir extracted
asahi-fwextract ${cfg.peripheralFirmwareDirectory} extracted
mkdir -p $out/lib/firmware
cat extracted/firmware.cpio | cpio -id --quiet --no-absolute-filenames
mv vendorfw/* $out/lib/firmware
'';
})
];

nativeBuildInputs = [ pkgs'.asahi-fwextract pkgs.cpio ];
boot.postBootCommands = mkIf (!cfg.usePeripheralFirmwareFromNixStore) ''
echo Extracting Asahi firmware...
mkdir -p /tmp/.fwsetup/{esp,extracted}
buildCommand = ''
mkdir extracted
asahi-fwextract ${config.hardware.asahi.peripheralFirmwareDirectory} extracted
mount /dev/disk/by-partuuid/`cat /proc/device-tree/chosen/asahi,efi-system-partition` /tmp/.fwsetup/esp
${pkgs'.asahi-fwextract}/bin/asahi-fwextract /tmp/.fwsetup/esp/asahi /tmp/.fwsetup/extracted
umount /tmp/.fwsetup/esp
mkdir -p $out/lib/firmware
cat extracted/firmware.cpio | cpio -id --quiet --no-absolute-filenames
mv vendorfw/* $out/lib/firmware
'';
})
];
pushd /tmp/.fwsetup/
cat /tmp/.fwsetup/extracted/firmware.cpio | ${pkgs.cpio}/bin/cpio -id --quiet --no-absolute-filenames
mkdir -p /lib/firmware
mv vendorfw/* /lib/firmware
popd
rm -rf /tmp/.fwsetup
'';
};

options.hardware.asahi = {
extractPeripheralFirmware = lib.mkOption {
usePeripheralFirmwareFromNixStore = lib.mkOption {
type = lib.types.bool;
default = true;
default = false;
description = ''
Automatically extract the non-free non-redistributable peripheral
firmware necessary for features like Wi-Fi.
By default, the non-free non-redistributable peripheral firmware is
automatically extracted every boot. If you want more purity,
this option will add the firmware to the Nix Store and manage it
like all other firmware in NixOS.
The firmware is necessary for features like Wi-Fi.
It is not recommended for flake users to enable this option as the
firmware is non-redistributable.
'';
};

Expand Down
20 changes: 6 additions & 14 deletions docs/uefi-standalone.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ Start the Mac, and U-Boot should start booting from the USB drive automatically.

<details>
<summary>If "mounting `/dev/root` on `/mnt-root/iso` failed: No such file or directory" during boot…</summary>

1. Was the ISO transferred to your flash drive correctly as described above? `dd` is the only correct way to do this. The ISO must be transferred to the drive block device itself, not a partition on the drive.
2. There is sometimes a [race condition](https://github.com/tpwrules/nixos-apple-silicon/issues/60) which causes booting to fail. Reboot the machine and try again.
3. Some flash drives have quirks. Try a different drive, or use the following steps:
Expand Down Expand Up @@ -168,7 +168,7 @@ Identify the number of the new root partition (type code 8300, typically second
```
nixos# sgdisk /dev/nvme0n1 -p
Disk /dev/nvme0n1: 244276265 sectors, 931.8 GiB
Model: APPLE SSD AP1024Q
Model: APPLE SSD AP1024Q
Sector size (logical/physical): 4096/4096 bytes
Disk identifier (GUID): 27054D2E-307A-41AA-9A8C-3864D56FAF6B
Partition table holds up to 128 entries
Expand All @@ -180,9 +180,9 @@ Total free space is 0 sectors (0 bytes)
Number Start (sector) End (sector) Size Code Name
1 6 128005 500.0 MiB FFFF iBootSystemContainer
2 128006 219854567 838.2 GiB AF0A Container
3 219854568 220465127 2.3 GiB AF0A
4 220465128 220590311 489.0 MiB EF00
5 220590312 242965550 85.4 GiB 8300
3 219854568 220465127 2.3 GiB AF0A
4 220465128 220590311 489.0 MiB EF00
5 220590312 242965550 85.4 GiB 8300
6 242965551 244276259 5.0 GiB FFFF RecoveryOSContainer
```

Expand Down Expand Up @@ -236,15 +236,7 @@ If you used the cross-compiled installer image, i.e. you downloaded the ISO from

The configuration above is the minimum required to produce a bootable system, but you can further edit the file as desired to perform additional configuration. Uncomment the relevant options and change their values as explained in the file. Note that some advertised features may not work properly at this time. Refer to the [NixOS installation manual](https://nixos.org/manual/nixos/stable/index.html#ch-configuration) for further guidance.

Various non-free non-redistributable peripheral firmware files are required to use system hardware like Wi-Fi. The Asahi Linux installer grabs these from macOS and stores them on the EFI system partition when it is created. The NixOS installer loads them from there while booting so that all hardware is available during installation. By default, the Apple Silicon support module will automatically reference the files in the EFI system partition and incorporate them into your configuration to be managed by the normal NixOS mechanisms.

Currently, the only supported way to update the peripheral firmware files is to destroy and re-create the EFI system partition, so they will not change unexpectedly. If you do not want the impurity of referencing them (or are using flakes where this is prohibited), copy them off the EFI system partition (e.g. on the installation ISO `mkdir -p /mnt/etc/nixos/firmware && cp /mnt/boot/asahi/{all_firmware.tar.gz,kernelcache*} /mnt/etc/nixos/firmware`) and specify this path in your configuration:
```
# Specify path to peripheral firmware files.
hardware.asahi.peripheralFirmwareDirectory = ./firmware;
# Or disable extraction and management of them completely.
# hardware.asahi.extractPeripheralFirmware = false;
```
Various non-free non-redistributable peripheral firmware files are required to use system hardware like Wi-Fi. The Asahi Linux installer grabs these from macOS and stores them on the EFI system partition when it is created. The NixOS installer loads them from there while booting so that all hardware is available during installation. By default, the Apple Silicon support module will also load the firmware from EFI system partition rather than being managed by the normal NixOS mechanisms.

You can choose to build the Asahi kernel with a 4K page size by enabling the appropriate option. This results in a reduction in raw compilation speed of 10-25%, but improves software compatibility in some cases (such as with Chromium/Electron and x86 emulation).
```
Expand Down
23 changes: 1 addition & 22 deletions iso-configuration/installer-configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
swapDevices = lib.mkOverride 60 [ ];
fileSystems = lib.mkOverride 60 config.lib.isoFileSystems;

boot.postBootCommands = let
inherit (config.hardware.asahi.pkgs) asahi-fwextract;
in ''
boot.postBootCommands = ''
for o in $(</proc/cmdline); do
case "$o" in
live.nixos.passwd=*)
Expand All @@ -39,26 +37,8 @@
;;
esac
done
echo Extracting Asahi firmware...
mkdir -p /tmp/.fwsetup/{esp,extracted}
mount /dev/disk/by-partuuid/`cat /proc/device-tree/chosen/asahi,efi-system-partition` /tmp/.fwsetup/esp
${asahi-fwextract}/bin/asahi-fwextract /tmp/.fwsetup/esp/asahi /tmp/.fwsetup/extracted
umount /tmp/.fwsetup/esp
pushd /tmp/.fwsetup/
cat /tmp/.fwsetup/extracted/firmware.cpio | ${pkgs.cpio}/bin/cpio -id --quiet --no-absolute-filenames
mkdir -p /lib/firmware
mv vendorfw/* /lib/firmware
popd
rm -rf /tmp/.fwsetup
'';

# can't legally be incorporated into the installer image
# (and is automatically extracted at boot above)
hardware.asahi.extractPeripheralFirmware = false;

isoImage.squashfsCompression = "zstd -Xcompression-level 6";

environment.systemPackages = with pkgs; [
Expand Down Expand Up @@ -87,7 +67,6 @@
enable = true;
settings.General.EnableNetworkConfiguration = true;
};


nixpkgs.overlays = [
(final: prev: {
Expand Down

0 comments on commit 488feab

Please sign in to comment.