diff --git a/raspberry-pi/2/default.nix b/raspberry-pi/2/default.nix index 2e61025..c917887 100644 --- a/raspberry-pi/2/default.nix +++ b/raspberry-pi/2/default.nix @@ -3,7 +3,13 @@ { boot = { consoleLogLevel = lib.mkDefault 7; - kernelPackages = lib.mkDefault pkgs.linuxPackages_rpi2; + kernelPackages = lib.mkDefault ( + pkgs.linuxPackagesFor ( + pkgs.callPackage ../common/kernel.nix { + rpiVersion = 2; + } + ) + ); kernelParams = [ "dwc_otg.lpm_enable=0" "console=ttyAMA0,115200" @@ -17,7 +23,7 @@ }; }; - nixpkgs.config.platform = lib.systems.platforms.raspberrypi2; + nixpkgs.config.platform = lib.systems.platforms.armv7l-hf-multiplatform; # cpufrequtils doesn't build on ARM powerManagement.enable = lib.mkDefault false; diff --git a/raspberry-pi/3/default.nix b/raspberry-pi/3/default.nix index e7d7c4c..6472c6b 100644 --- a/raspberry-pi/3/default.nix +++ b/raspberry-pi/3/default.nix @@ -6,7 +6,13 @@ { boot = { - kernelPackages = lib.mkDefault pkgs.linuxKernel.packages.linux_rpi3; + kernelPackages = lib.mkDefault ( + pkgs.linuxPackagesFor ( + pkgs.callPackage ../common/kernel.nix { + rpiVersion = 3; + } + ) + ); initrd.availableKernelModules = [ "usbhid" "usb-storage" diff --git a/raspberry-pi/4/default.nix b/raspberry-pi/4/default.nix index 29f62db..9efb4fc 100644 --- a/raspberry-pi/4/default.nix +++ b/raspberry-pi/4/default.nix @@ -28,7 +28,13 @@ ]; boot = { - kernelPackages = lib.mkDefault pkgs.linuxKernel.packages.linux_rpi4; + kernelPackages = lib.mkDefault ( + pkgs.linuxPackagesFor ( + pkgs.callPackage ../common/kernel.nix { + rpiVersion = 4; + } + ) + ); initrd.availableKernelModules = [ "usbhid" "usb-storage" @@ -56,5 +62,7 @@ } ]; - hardware.firmware = [ pkgs.raspberrypiWirelessFirmware ]; + hardware.firmware = [ + (pkgs.callPackage ../common/raspberry-pi-wireless-firmware.nix { }) + ]; } diff --git a/raspberry-pi/5/default.nix b/raspberry-pi/5/default.nix index 020dc97..f8d82a9 100644 --- a/raspberry-pi/5/default.nix +++ b/raspberry-pi/5/default.nix @@ -4,15 +4,15 @@ config, ... }: -let - linux_rpi5 = pkgs.linux_rpi4.override { - rpiVersion = 5; - argsOverride.defconfig = "bcm2712_defconfig"; - }; -in { boot = { - kernelPackages = lib.mkDefault (pkgs.linuxPackagesFor linux_rpi5); + kernelPackages = lib.mkDefault ( + pkgs.linuxPackagesFor ( + pkgs.callPackage ../common/kernel.nix { + rpiVersion = 5; + } + ) + ); initrd.availableKernelModules = [ "nvme" "usbhid" diff --git a/raspberry-pi/common/kernel.nix b/raspberry-pi/common/kernel.nix new file mode 100644 index 0000000..41a678d --- /dev/null +++ b/raspberry-pi/common/kernel.nix @@ -0,0 +1,113 @@ +{ + stdenv, + lib, + pkgs, + fetchFromGitHub, + buildLinux, + rpiVersion, + ... +}@args: + +let + # NOTE: raspberryPiWirelessFirmware should be updated with this + modDirVersion = "6.12.47"; + tag = "stable_20250916"; + hash = "sha256-HG8Oc04V2t54l0SOn4gKmNJWQUrZfjWusgKcWvx74H0=="; +in +lib.overrideDerivation + (buildLinux ( + args + // { + version = "${modDirVersion}-${tag}"; + inherit modDirVersion; + pname = "linux-rpi"; + + src = fetchFromGitHub { + owner = "raspberrypi"; + repo = "linux"; + inherit tag hash; + }; + + defconfig = + { + "1" = "bcmrpi_defconfig"; + "2" = "bcm2709_defconfig"; + "3" = if stdenv.hostPlatform.isAarch64 then "bcm2711_defconfig" else "bcm2709_defconfig"; + "4" = "bcm2711_defconfig"; + "5" = "bcm2712_defconfig"; + } + .${toString rpiVersion}; + + features = { + efiBootStub = false; + } + // (args.features or { }); + + isLTS = true; + + kernelPatches = with pkgs.kernelPatches; [ + bridge_stp_helper + request_key_helper + ]; + + extraMeta = + if (rpiVersion < 3) then + { + platforms = with lib.platforms; lib.intersectLists arm linux; + hydraPlatforms = [ ]; + } + else + { + platforms = with lib.platforms; lib.intersectLists (arm ++ aarch64) linux; + hydraPlatforms = [ "aarch64-linux" ]; + }; + ignoreConfigErrors = true; + } + // (args.argsOverride or { }) + )) + (_oldAttrs: { + postConfigure = '' + # The v7 defconfig has this set to '-v7' which screws up our modDirVersion. + sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/' + sed -i $buildRoot/include/config/auto.conf -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/' + ''; + + # Make copies of the DTBs named after the upstream names so that U-Boot finds them. + # This is ugly as heck, but I don't know a better solution so far. + postFixup = '' + dtbDir=${if stdenv.hostPlatform.isAarch64 then "$out/dtbs/broadcom" else "$out/dtbs"} + rm $dtbDir/bcm283*.dtb + copyDTB() { + cp -v "$dtbDir/$1" "$dtbDir/$2" + } + '' + + lib.optionalString (lib.elem stdenv.hostPlatform.system [ "armv6l-linux" ]) '' + copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero.dtb + copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero-w.dtb + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-a.dtb + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b.dtb + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b-rev2.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-a-plus.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-b-plus.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-zero.dtb + copyDTB bcm2708-rpi-cm.dtb bcm2835-rpi-cm.dtb + '' + + lib.optionalString (lib.elem stdenv.hostPlatform.system [ "armv7l-linux" ]) '' + copyDTB bcm2709-rpi-2-b.dtb bcm2836-rpi-2-b.dtb + '' + + + lib.optionalString + (lib.elem stdenv.hostPlatform.system [ + "armv7l-linux" + "aarch64-linux" + ]) + '' + copyDTB bcm2710-rpi-zero-2.dtb bcm2837-rpi-zero-2.dtb + copyDTB bcm2710-rpi-zero-2-w.dtb bcm2837-rpi-zero-2-w.dtb + copyDTB bcm2710-rpi-3-b.dtb bcm2837-rpi-3-b.dtb + copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-a-plus.dtb + copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-b-plus.dtb + copyDTB bcm2710-rpi-cm3.dtb bcm2837-rpi-cm3.dtb + copyDTB bcm2711-rpi-4-b.dtb bcm2838-rpi-4-b.dtb + ''; + }) diff --git a/raspberry-pi/common/raspberry-pi-wireless-firmware.nix b/raspberry-pi/common/raspberry-pi-wireless-firmware.nix new file mode 100644 index 0000000..466f563 --- /dev/null +++ b/raspberry-pi/common/raspberry-pi-wireless-firmware.nix @@ -0,0 +1,64 @@ +{ + lib, + stdenvNoCC, + fetchFromGitHub, +}: + +stdenvNoCC.mkDerivation { + pname = "raspberrypi-wireless-firmware"; + version = "0-unstable-2025-04-08"; + + srcs = [ + (fetchFromGitHub { + name = "bluez-firmware"; + owner = "RPi-Distro"; + repo = "bluez-firmware"; + rev = "2bbfb8438e824f5f61dae3f6ebb367a6129a4d63"; + hash = "sha256-t+D4VUfEIov83KV4wiKp6TqXTHXGkxg/mANi4GW7QHs="; + }) + (fetchFromGitHub { + name = "firmware-nonfree"; + owner = "RPi-Distro"; + repo = "firmware-nonfree"; + rev = "c9d3ae6584ab79d19a4f94ccf701e888f9f87a53"; + hash = "sha256-5ywIPs3lpmqVOVP3B75H577fYkkucDqB7htY2U1DW8U="; + }) + ]; + + sourceRoot = "."; + + dontBuild = true; + # Firmware blobs do not need fixing and should not be modified + dontFixup = true; + + installPhase = '' + runHook preInstall + mkdir -p "$out/lib/firmware/brcm" + + # Wifi firmware + cp -rv "$NIX_BUILD_TOP/firmware-nonfree/debian/config/brcm80211/." "$out/lib/firmware/" + + # Bluetooth firmware + cp -rv "$NIX_BUILD_TOP/bluez-firmware/debian/firmware/broadcom/." "$out/lib/firmware/brcm" + + # brcmfmac43455-sdio.bin is a symlink to the non-existent path: ../cypress/cyfmac43455-sdio.bin. + # See https://github.com/RPi-Distro/firmware-nonfree/issues/26 + ln -s "./cyfmac43455-sdio-standard.bin" "$out/lib/firmware/cypress/cyfmac43455-sdio.bin" + + pushd $out/lib/firmware/brcm &>/dev/null + # Symlinks for Zero 2W + ln -s "./brcmfmac43436-sdio.clm_blob" "$out/lib/firmware/brcm/brcmfmac43430b0-sdio.clm_blob" + popd &>/dev/null + + runHook postInstall + ''; + + meta = { + description = "Firmware for builtin Wifi/Bluetooth devices in the Raspberry Pi 3+ and Zero W"; + homepage = "https://github.com/RPi-Distro/firmware-nonfree"; + license = lib.licenses.unfreeRedistributableFirmware; + maintainers = with lib.maintainers; [ lopsided98 ]; + platforms = lib.platforms.linux; + sourceProvenance = with lib.sourceTypes; [ binaryFirmware ]; + }; +}