diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac55dd2a..9999d49b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,11 +11,11 @@ jobs: steps: - uses: actions/checkout@v5 - uses: cachix/install-nix-action@v31 - - run: cd tests && nix fmt .. -- --fail-on-change + - run: nix build .#checks.x86_64-linux.formatting tests: needs: nixfmt runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: cachix/install-nix-action@v31 - - run: nix run ./tests#run . \ No newline at end of file + - run: nix run .#run-tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63a147a7..93564142 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ Link the profile in the table in README.md and in flake.nix. ## 3. Testing -Run `nix run ./tests#run .` to evaluate all hardware profiles. +Run `nix run .#run-tests` to evaluate all hardware profiles. Because profiles can only be tested with the appropriate hardware, quality assurance is up to *you*. diff --git a/README.md b/README.md index cb513494..bd4fd3c9 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ See code for all available configurations. | [Dell XPS 17 9700, nvidia](dell/xps/17-9700/nvidia) | `` | `dell-xps-17-9700-nvidia` | | [Dell XPS 17 9710, intel only](dell/xps/17-9710/intel) | `` | `dell-xps-17-9710-intel` | | [Framework 11th Gen Intel Core](framework/13-inch/11th-gen-intel) | `` | `framework-11th-gen-intel` | -| [Framework 12th Gen Intel Core](framework/12-inch/12th-gen-intel) | `` | `framework-12th-gen-intel` | +| [Framework 12th Gen Intel Core](framework/13-inch/12th-gen-intel) | `` | `framework-12th-gen-intel` | | [Framework 13th Gen Intel Core](framework/13-inch/13th-gen-intel) | `` | `framework-13th-gen-intel` | | [Framework Intel Core Ultra Series 1](framework/13-inch/intel-core-ultra-series1) | `` | `framework-intel-core-ultra-series1` | | [Framework 13 AMD Ryzen 7040 Series](framework/13-inch/7040-amd) | `` | `framework-13-7040-amd` | diff --git a/apple/imac/14-2/default.nix b/apple/imac/14-2/default.nix index c20acfd7..5dd218c5 100644 --- a/apple/imac/14-2/default.nix +++ b/apple/imac/14-2/default.nix @@ -29,7 +29,6 @@ "bcma" ]; kernelPackages = lib.mkIf (lib.versionOlder pkgs.linux.version "6.0") pkgs.linuxPackages_latest; - extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; }; hardware = { diff --git a/apple/macbook-air/6/default.nix b/apple/macbook-air/6/default.nix index 3e927352..67f3a706 100644 --- a/apple/macbook-air/6/default.nix +++ b/apple/macbook-air/6/default.nix @@ -3,8 +3,6 @@ { imports = [ ../. ]; - boot.kernelModules = [ "wl" ]; - boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; boot.blacklistedKernelModules = [ "bcma" ]; boot = { diff --git a/apple/macbook-pro/11-1/default.nix b/apple/macbook-pro/11-1/default.nix index 6c9509b2..95f8c289 100644 --- a/apple/macbook-pro/11-1/default.nix +++ b/apple/macbook-pro/11-1/default.nix @@ -6,9 +6,5 @@ ../../../common/cpu/intel/haswell ]; - # broadcom-wl hardware.enableRedistributableFirmware = lib.mkDefault true; - # nixos-generate-config doesn't detect this automatically. - boot.extraModulePackages = with config.boot.kernelPackages; [ broadcom_sta ]; - boot.kernelModules = [ "wl" ]; } diff --git a/dell/inspiron/3442/default.nix b/dell/inspiron/3442/default.nix index 0d298ff3..adbb0c16 100644 --- a/dell/inspiron/3442/default.nix +++ b/dell/inspiron/3442/default.nix @@ -6,16 +6,8 @@ ../../../common/pc/laptop ]; - hardware.enableAllFirmware = lib.mkDefault true; - services = { fwupd.enable = lib.mkDefault true; thermald.enable = lib.mkDefault true; }; - - boot = { - # needs to be explicitly loaded or else bluetooth/wifi won't work. - kernelModules = [ "wl" ]; - extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; - }; } diff --git a/dell/xps/13-9343/default.nix b/dell/xps/13-9343/default.nix index e98bb09b..28d6e22f 100644 --- a/dell/xps/13-9343/default.nix +++ b/dell/xps/13-9343/default.nix @@ -13,11 +13,8 @@ }; boot = { - # needs to be explicitly loaded or else bluetooth/wifi won't work kernelModules = [ "kvm-intel" - "wl" ]; - extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; }; } diff --git a/flake.nix b/flake.nix index 2412e662..610e8bb4 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,39 @@ description = "nixos-hardware"; outputs = - { ... }: + { self, ... }: + let + # Import private inputs (for development) + privateInputs = + (import ./tests/flake-compat.nix { + src = ./tests; + }).defaultNix; + + systems = [ + "aarch64-linux" + "riscv64-linux" + "x86_64-linux" + ]; + + formatSystems = [ + "aarch64-linux" + "x86_64-linux" + "aarch64-darwin" + ]; + + # Helper to iterate over systems + eachSystem = + f: + privateInputs.nixos-unstable-small.lib.genAttrs systems ( + system: f privateInputs.nixos-unstable-small.legacyPackages.${system} system + ); + + eachSystemFormat = + f: + privateInputs.nixos-unstable-small.lib.genAttrs formatSystems ( + system: f privateInputs.nixos-unstable-small.legacyPackages.${system} system + ); + in { nixosModules = @@ -331,6 +363,7 @@ nxp-imx8mp-evk = import ./nxp/imx8mp-evk; nxp-imx8mq-evk = import ./nxp/imx8mq-evk; nxp-imx8qm-mek = import ./nxp/imx8qm-mek; + nxp-imx93-evk = import ./nxp/imx93-evk; hardkernel-odroid-hc4 = import ./hardkernel/odroid-hc4; hardkernel-odroid-h3 = import ./hardkernel/odroid-h3; hardkernel-odroid-h4 = import ./hardkernel/odroid-h4; @@ -413,5 +446,40 @@ common-pc-laptop-ssd = import ./common/pc/ssd; common-pc-ssd = import ./common/pc/ssd; }; + + # Add formatter for `nix fmt` + formatter = eachSystemFormat ( + pkgs: _system: + (privateInputs.treefmt-nix.lib.evalModule pkgs ./tests/treefmt.nix).config.build.wrapper + ); + + # Add packages + packages = eachSystem ( + pkgs: _system: { + run-tests = pkgs.callPackage ./tests/run-tests.nix { + inherit self; + }; + } + ); + + # Add checks for `nix run .#run-tests` + checks = eachSystem ( + pkgs: system: + let + treefmtEval = privateInputs.treefmt-nix.lib.evalModule pkgs ./tests/treefmt.nix; + nixosTests = import ./tests/nixos-tests.nix { + inherit + self + privateInputs + system + pkgs + ; + }; + in + pkgs.lib.optionalAttrs (self.formatter ? ${system}) { + formatting = treefmtEval.config.build.check self; + } + // nixosTests + ); }; } diff --git a/framework/13-inch/common/amd.nix b/framework/13-inch/common/amd.nix index ae35fffe..4a89f8da 100644 --- a/framework/13-inch/common/amd.nix +++ b/framework/13-inch/common/amd.nix @@ -6,19 +6,18 @@ ../../../common/gpu/amd ]; - boot.kernelParams = - [ - # There seems to be an issue with panel self-refresh (PSR) that - # causes hangs for users. - # - # https://community.frame.work/t/fedora-kde-becomes-suddenly-slow/58459 - # https://gitlab.freedesktop.org/drm/amd/-/issues/3647 - "amdgpu.dcdebugmask=0x10" - ] - # Workaround for SuspendThenHibernate: https://lore.kernel.org/linux-kernel/20231106162310.85711-1-mario.limonciello@amd.com/ - ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") [ - "rtc_cmos.use_acpi_alarm=1" - ]; + boot.kernelParams = [ + # There seems to be an issue with panel self-refresh (PSR) that + # causes hangs for users. + # + # https://community.frame.work/t/fedora-kde-becomes-suddenly-slow/58459 + # https://gitlab.freedesktop.org/drm/amd/-/issues/3647 + "amdgpu.dcdebugmask=0x10" + ] + # Workaround for SuspendThenHibernate: https://lore.kernel.org/linux-kernel/20231106162310.85711-1-mario.limonciello@amd.com/ + ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") [ + "rtc_cmos.use_acpi_alarm=1" + ]; # AMD has better battery life with PPD over TLP: # https://community.frame.work/t/responded-amd-7040-sleep-states/38101/13 diff --git a/framework/13-inch/common/intel.nix b/framework/13-inch/common/intel.nix index 6248e75f..c46652cb 100644 --- a/framework/13-inch/common/intel.nix +++ b/framework/13-inch/common/intel.nix @@ -9,16 +9,15 @@ ../../../common/cpu/intel ]; - boot.kernelParams = - [ - # For Power consumption - # https://community.frame.work/t/linux-battery-life-tuning/6665/156 - "nvme.noacpi=1" - ] - # Fixes a regression in s2idle, making it more power efficient than deep sleep - # Update 04/2024: It appears that s2idle-regression got fixed in newer kernel-versions (SebTM) - # (see: https://github.com/NixOS/nixos-hardware/pull/903#discussion_r1556096657) - ++ lib.lists.optional (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") "acpi_osi=\"!Windows 2020\""; + boot.kernelParams = [ + # For Power consumption + # https://community.frame.work/t/linux-battery-life-tuning/6665/156 + "nvme.noacpi=1" + ] + # Fixes a regression in s2idle, making it more power efficient than deep sleep + # Update 04/2024: It appears that s2idle-regression got fixed in newer kernel-versions (SebTM) + # (see: https://github.com/NixOS/nixos-hardware/pull/903#discussion_r1556096657) + ++ lib.lists.optional (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") "acpi_osi=\"!Windows 2020\""; # Requires at least 5.16 for working wi-fi and bluetooth. # https://community.frame.work/t/using-the-ax210-with-linux-on-the-framework-laptop/1844/89 diff --git a/framework/13-inch/intel-core-ultra-series1/default.nix b/framework/13-inch/intel-core-ultra-series1/default.nix index 7553e687..88393ab4 100644 --- a/framework/13-inch/intel-core-ultra-series1/default.nix +++ b/framework/13-inch/intel-core-ultra-series1/default.nix @@ -20,30 +20,6 @@ lib.mkDefault pkgs.linuxPackages_latest ); - # Intel NPU Driver - # https://discourse.nixos.org/t/new-installation-on-asus-zenbook-ux5406-intel-vpu-firmware-error-2/58732/2 - hardware.firmware = lib.optionals (config.hardware.enableRedistributableFirmware) [ - ( - let - model = "37xx"; - version = "0.0"; - - firmware = pkgs.fetchurl { - url = "https://github.com/intel/linux-npu-driver/raw/v1.13.0/firmware/bin/vpu_${model}_v${version}.bin"; - hash = "sha256-Mpoeq8HrwChjtHALsss/7QsFtDYAoFNsnhllU0xp3os="; - }; - in - pkgs.runCommand "intel-vpu-firmware-${model}-${version}" { } '' - mkdir -p "$out/lib/firmware/intel/vpu" - cp '${firmware}' "$out/lib/firmware/intel/vpu/vpu_${model}_v${version}.bin" - '' - ) - ]; - - warnings = lib.mkIf (!config.hardware.enableRedistributableFirmware) [ - ''For Intel NPU support, set the option: hardware.enableRedistributableFirmware = true;'' - ]; - hardware.framework.laptop13.audioEnhancement.rawDeviceName = lib.mkDefault "alsa_output.pci-0000_00_1f.3.analog-stereo"; } diff --git a/framework/16-inch/common/amd.nix b/framework/16-inch/common/amd.nix index ae35fffe..4a89f8da 100644 --- a/framework/16-inch/common/amd.nix +++ b/framework/16-inch/common/amd.nix @@ -6,19 +6,18 @@ ../../../common/gpu/amd ]; - boot.kernelParams = - [ - # There seems to be an issue with panel self-refresh (PSR) that - # causes hangs for users. - # - # https://community.frame.work/t/fedora-kde-becomes-suddenly-slow/58459 - # https://gitlab.freedesktop.org/drm/amd/-/issues/3647 - "amdgpu.dcdebugmask=0x10" - ] - # Workaround for SuspendThenHibernate: https://lore.kernel.org/linux-kernel/20231106162310.85711-1-mario.limonciello@amd.com/ - ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") [ - "rtc_cmos.use_acpi_alarm=1" - ]; + boot.kernelParams = [ + # There seems to be an issue with panel self-refresh (PSR) that + # causes hangs for users. + # + # https://community.frame.work/t/fedora-kde-becomes-suddenly-slow/58459 + # https://gitlab.freedesktop.org/drm/amd/-/issues/3647 + "amdgpu.dcdebugmask=0x10" + ] + # Workaround for SuspendThenHibernate: https://lore.kernel.org/linux-kernel/20231106162310.85711-1-mario.limonciello@amd.com/ + ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "6.8") [ + "rtc_cmos.use_acpi_alarm=1" + ]; # AMD has better battery life with PPD over TLP: # https://community.frame.work/t/responded-amd-7040-sleep-states/38101/13 diff --git a/framework/kmod.nix b/framework/kmod.nix index 7cb53746..9d98a734 100644 --- a/framework/kmod.nix +++ b/framework/kmod.nix @@ -1,56 +1,35 @@ { config, lib, - pkgs, ... }: -let - kernel_version_compatible = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.10"; -in { options.hardware.framework.enableKmod = - (lib.mkEnableOption "Enable the community created Framework kernel module that allows interacting with the embedded controller from sysfs.") + (lib.mkEnableOption "the community-created Framework kernel module that allows interacting with the embedded controller from sysfs.") // { # enable by default on NixOS >= 24.05 and kernel >= 6.10 - default = lib.and (lib.versionAtLeast (lib.versions.majorMinor lib.version) "24.05") kernel_version_compatible; - defaultText = "enabled by default on NixOS >= 24.05 and kernel >= 6.10"; + default = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.10"; + defaultText = "enabled by default if kernel >= 6.10"; }; - config.boot = lib.mkIf config.hardware.framework.enableKmod { - extraModulePackages = with config.boot.kernelPackages; [ - framework-laptop-kmod - ]; - - # https://github.com/DHowett/framework-laptop-kmod?tab=readme-ov-file#usage - kernelModules = [ - "cros_ec" - "cros_ec_lpcs" - ]; - - # add required patch if enabled on kernel <6.10 - kernelPatches = lib.mkIf (!kernel_version_compatible) [ - rec { - name = "platform/chrome: cros_ec_lpc: add support for AMD Framework Laptops"; - msgid = "20240403004713.130365-1-dustin@howett.net"; - version = "3"; - hash = "sha256-aQSyys8CMzlj9EdNhg8vtp76fg1qEwUVeJL0E+8w5HU="; - patch = - pkgs.runCommandLocal "patch-${msgid}" - { - nativeBuildInputs = with pkgs; [ - b4 - git - cacert - ]; - SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; - - outputHash = hash; - } - '' - export HOME="$TMP" - PYTHONHASHSEED=0 ${pkgs.b4}/bin/b4 -n am -C -T -v ${version} -o- "${msgid}" > "$out" - ''; + config = lib.mkIf config.hardware.framework.enableKmod { + assertions = [ + { + assertion = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.10"; + message = "The framework laptop kernel module requires Linux 6.10 or above"; } ]; + + boot = { + extraModulePackages = with config.boot.kernelPackages; [ + framework-laptop-kmod + ]; + + # https://github.com/DHowett/framework-laptop-kmod?tab=readme-ov-file#usage + kernelModules = [ + "cros_ec" + "cros_ec_lpcs" + ]; + }; }; } diff --git a/lenovo/legion/15ach6h/nvidia/default.nix b/lenovo/legion/15ach6h/nvidia/default.nix index 37dd1148..25bf31bf 100644 --- a/lenovo/legion/15ach6h/nvidia/default.nix +++ b/lenovo/legion/15ach6h/nvidia/default.nix @@ -10,12 +10,11 @@ # remove all packages for amd igpu. I only removed amdgpu from # services.xserver.videoDrivers by overriding. This is because the specialization # of nix cannot implement such an operation as canceling an import. - hardware = - { - nvidia.prime.offload.enable = false; - } - // lib.optionalAttrs (options ? amdgpu.opencl.enable) { - # introduced in https://github.com/NixOS/nixpkgs/pull/319865 - amdgpu.opencl.enable = lib.mkDefault false; - }; + hardware = { + nvidia.prime.offload.enable = false; + } + // lib.optionalAttrs (options ? amdgpu.opencl.enable) { + # introduced in https://github.com/NixOS/nixpkgs/pull/319865 + amdgpu.opencl.enable = lib.mkDefault false; + }; } diff --git a/lenovo/legion/16ach6h/nvidia/default.nix b/lenovo/legion/16ach6h/nvidia/default.nix index 37dd1148..25bf31bf 100644 --- a/lenovo/legion/16ach6h/nvidia/default.nix +++ b/lenovo/legion/16ach6h/nvidia/default.nix @@ -10,12 +10,11 @@ # remove all packages for amd igpu. I only removed amdgpu from # services.xserver.videoDrivers by overriding. This is because the specialization # of nix cannot implement such an operation as canceling an import. - hardware = - { - nvidia.prime.offload.enable = false; - } - // lib.optionalAttrs (options ? amdgpu.opencl.enable) { - # introduced in https://github.com/NixOS/nixpkgs/pull/319865 - amdgpu.opencl.enable = lib.mkDefault false; - }; + hardware = { + nvidia.prime.offload.enable = false; + } + // lib.optionalAttrs (options ? amdgpu.opencl.enable) { + # introduced in https://github.com/NixOS/nixpkgs/pull/319865 + amdgpu.opencl.enable = lib.mkDefault false; + }; } diff --git a/lenovo/legion/16achg6/nvidia/default.nix b/lenovo/legion/16achg6/nvidia/default.nix index d279b6a2..58b7ad23 100644 --- a/lenovo/legion/16achg6/nvidia/default.nix +++ b/lenovo/legion/16achg6/nvidia/default.nix @@ -3,12 +3,11 @@ { imports = [ ../hybrid ]; services.xserver.videoDrivers = [ "nvidia" ]; - hardware = - { - nvidia.prime.offload.enable = false; - } - // lib.optionalAttrs (options ? amdgpu.opencl.enable) { - # introduced in https://github.com/NixOS/nixpkgs/pull/319865 - amdgpu.opencl.enable = lib.mkDefault false; - }; + hardware = { + nvidia.prime.offload.enable = false; + } + // lib.optionalAttrs (options ? amdgpu.opencl.enable) { + # introduced in https://github.com/NixOS/nixpkgs/pull/319865 + amdgpu.opencl.enable = lib.mkDefault false; + }; } diff --git a/lenovo/thinkpad/p14s/amd/gen2/default.nix b/lenovo/thinkpad/p14s/amd/gen2/default.nix index b79e1cf3..a1cd731c 100644 --- a/lenovo/thinkpad/p14s/amd/gen2/default.nix +++ b/lenovo/thinkpad/p14s/amd/gen2/default.nix @@ -14,9 +14,10 @@ # amdgpu.backlight=0 makes the backlight work # acpi_backlight=none allows the backlight save/load systemd service to work on older kernel versions - boot.kernelParams = - [ "amdgpu.backlight=0" ] - ++ lib.optional (lib.versionOlder config.boot.kernelPackages.kernel.version "6.1.6") "acpi_backlight=none"; + boot.kernelParams = [ + "amdgpu.backlight=0" + ] + ++ lib.optional (lib.versionOlder config.boot.kernelPackages.kernel.version "6.1.6") "acpi_backlight=none"; # For mainline support of rtw89 wireless networking boot.kernelPackages = lib.mkIf (lib.versionOlder pkgs.linux.version "5.16") pkgs.linuxPackages_latest; diff --git a/microsoft/surface/common/kernel/linux-package.nix b/microsoft/surface/common/kernel/linux-package.nix index a66aabc4..f9f96184 100644 --- a/microsoft/surface/common/kernel/linux-package.nix +++ b/microsoft/surface/common/kernel/linux-package.nix @@ -24,19 +24,18 @@ let let inherit (builtins) removeAttrs; - args' = - { - inherit - src - version - modDirVersion - kernelPatches - ; - } - // removeAttrs args [ - "url" - "sha256" - ]; + args' = { + inherit + src + version + modDirVersion + kernelPatches + ; + } + // removeAttrs args [ + "url" + "sha256" + ]; linuxPackage = buildLinux args'; linuxPackages' = recurseIntoAttrs (linuxPackagesFor linuxPackage); in diff --git a/mnt/reform/rk3588/installer.nix b/mnt/reform/rk3588/installer.nix index af7c5580..4e0c12c0 100644 --- a/mnt/reform/rk3588/installer.nix +++ b/mnt/reform/rk3588/installer.nix @@ -139,7 +139,8 @@ device = "/iso/nix-store.squashfs"; options = [ "loop" - ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi"; + ] + ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi"; neededForBoot = true; }; diff --git a/nxp/README.md b/nxp/README.md index f8ccefa0..cf1f5d2a 100644 --- a/nxp/README.md +++ b/nxp/README.md @@ -21,17 +21,18 @@ Code snippet example that enables imx8qm configuration: } ``` -### 2.2 For imx8mq-evk/imx8mp-evk +### 2.2 For imx8mq-evk/imx8mp-evk/imx93-evk This NXP overlay is used for generating sdimage. -Current configuration uses uboot as a bootloader. It provides an options to use optee-os which is currently disabled. It can be enabled using `enable-tee` boolean argument avalable in `imx8m-boot.nix`, which is `false` by default. +Current configuration uses uboot as a bootloader. It provides an options to use optee-os which is currently disabled. It can be enabled using `enable-tee` boolean argument avalable in `imx8m-boot.nix`, which is `false` by default in imx8m platform. -Code snippet example that enables 'imx8mp-evk/emx8mq-evk' configuration: +Code snippet example that enables 'imx8mp-evk/imx8mq-evk/imx93-evk' configuration: ``` { nixos-hardware, }: { system = "aarch64-linux"; modules = [ nixos-hardware.nixosModules.imx8mp-evk #For imx8mp-evk + #nixos-hardware.nixosModules.imx93-evk #For imx93-evk #nixos-hardware.nixosModules.imx8mq-evk #For imx8mq-evk ]; } diff --git a/nxp/common/bsp/imx-firmware.nix b/nxp/common/bsp/imx-firmware.nix index 46e905f8..c2d6a8ed 100644 --- a/nxp/common/bsp/imx-firmware.nix +++ b/nxp/common/bsp/imx-firmware.nix @@ -47,21 +47,20 @@ pkgs.stdenv.mkDerivation rec { ${firmwareSeco} --auto-accept --force ''; - filesToInstall = - [ - "firmware-imx-${fwHdmiVersion}/firmware/hdmi/cadence/dpfw.bin" - "firmware-imx-${fwHdmiVersion}/firmware/hdmi/cadence/hdmi?xfw.bin" - ] - ++ pkgs.lib.optional (targetBoard == "imx8qm") ( - "imx-sc-firmware-${fwScVersion}/mx8qm-mek-scfw-tcm.bin" - + " " - + "imx-seco-${fwSecoVersion}/firmware/seco/mx8qmb0-ahab-container.img" - ) - ++ pkgs.lib.optional (targetBoard == "imx8qxp") ( - "imx-sc-firmware-${fwScVersion}/mx8qx-mek-scfw-tcm.bin" - + " " - + "imx-seco-${fwSecoVersion}/firmware/seco/mx8qxc0-ahab-container.img" - ); + filesToInstall = [ + "firmware-imx-${fwHdmiVersion}/firmware/hdmi/cadence/dpfw.bin" + "firmware-imx-${fwHdmiVersion}/firmware/hdmi/cadence/hdmi?xfw.bin" + ] + ++ pkgs.lib.optional (targetBoard == "imx8qm") ( + "imx-sc-firmware-${fwScVersion}/mx8qm-mek-scfw-tcm.bin" + + " " + + "imx-seco-${fwSecoVersion}/firmware/seco/mx8qmb0-ahab-container.img" + ) + ++ pkgs.lib.optional (targetBoard == "imx8qxp") ( + "imx-sc-firmware-${fwScVersion}/mx8qx-mek-scfw-tcm.bin" + + " " + + "imx-seco-${fwSecoVersion}/firmware/seco/mx8qxc0-ahab-container.img" + ); installPhase = '' mkdir -p $out diff --git a/nxp/common/bsp/imx-linux-builder.nix b/nxp/common/bsp/imx-linux-builder.nix new file mode 100644 index 00000000..cc8fb934 --- /dev/null +++ b/nxp/common/bsp/imx-linux-builder.nix @@ -0,0 +1,56 @@ +# Parameterized Linux kernel builder for i.MX platforms +# This builder is used across i.MX93, i.MX8MP, i.MX8MQ and similar platforms +{ lib, pkgs, ... }@args: +let + inherit (pkgs) buildLinux; + + # Import common kernel configuration + kernelConfig = import ../lib/kernel-config.nix; +in +# Platform-specific parameters +{ + pname, + version, + src, + defconfig ? "imx_v8_defconfig", + # Optional parameters + extraConfig ? "", + kernelPatches ? [ ], + autoModules ? false, + ignoreConfigErrors ? true, + extraMeta ? { }, +}: +let + # Combine common i.MX kernel config with platform-specific config + finalExtraConfig = kernelConfig.imxCommonKernelConfig + extraConfig; +in +buildLinux ( + args + // rec { + inherit + version + defconfig + kernelPatches + autoModules + ignoreConfigErrors + ; + name = pname; + + # modDirVersion needs to be x.y.z, will automatically add .0 if needed + modDirVersion = version; + + extraConfig = finalExtraConfig; + + inherit src; + + meta = + with lib; + { + homepage = "https://github.com/nxp-imx/linux-imx"; + license = [ licenses.gpl2Only ]; + platforms = [ "aarch64-linux" ]; + } + // extraMeta; + } + // (args.argsOverride or { }) +) diff --git a/nxp/common/bsp/imx-optee-builder.nix b/nxp/common/bsp/imx-optee-builder.nix new file mode 100644 index 00000000..7d506fbe --- /dev/null +++ b/nxp/common/bsp/imx-optee-builder.nix @@ -0,0 +1,89 @@ +# Parameterized OP-TEE OS builder for i.MX platforms +# This builder is used across i.MX93, i.MX8MP, i.MX8MQ and similar platforms +{ + lib, + pkgs, + # Platform-specific parameters + pname, + version, + platformFlavor, + src, + # Optional parameters + meta ? { }, +}: +let + inherit (pkgs.buildPackages) python3; + toolchain = pkgs.gccStdenv.cc; + binutils = pkgs.gccStdenv.cc.bintools.bintools_bin; + cpp = pkgs.gcc; + + # Determine PLATFORM and PLATFORM_FLAVOR from platformFlavor + # Format can be either "imx-mx93evk" (full platform string) or "mx8mpevk" (just flavor, platform is "imx") + # Check if it starts with "imx-" to determine if it's a full platform string or just a flavor + hasFullPlatform = lib.hasPrefix "imx-" platformFlavor; + platform = if hasFullPlatform then platformFlavor else "imx"; + flavor = if hasFullPlatform then null else platformFlavor; +in +pkgs.stdenv.mkDerivation { + inherit pname version src; + + nativeBuildInputs = [ + python3 + ]; + + enableParallelBuilding = true; + + propagatedBuildInputs = with python3.pkgs; [ + pycryptodomex + pyelftools + cryptography + ]; + + # Common postPatch for all i.MX platforms + # This is the major source of code duplication - ~60 lines of identical substitutions + postPatch = '' + # Patch all script shebangs automatically + patchShebangs scripts/ + patchShebangs ta/ + + # Patch toolchain paths in mk/gcc.mk + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))objcopy" ${binutils}/bin/${toolchain.targetPrefix}objcopy + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))objdump" ${binutils}/bin/${toolchain.targetPrefix}objdump + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))nm" ${binutils}/bin/${toolchain.targetPrefix}nm + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))readelf" ${binutils}/bin/${toolchain.targetPrefix}readelf + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))ar" ${binutils}/bin/${toolchain.targetPrefix}ar + substituteInPlace mk/gcc.mk \ + --replace "\$(CROSS_COMPILE_\$(sm))cpp" ${cpp}/bin/cpp + ''; + + makeFlags = [ + "PLATFORM=${platform}" + ] + ++ lib.optionals (!hasFullPlatform) [ + "PLATFORM_FLAVOR=${flavor}" + ] + ++ [ + "CFG_ARM64_core=y" + "CFG_TEE_TA_LOG_LEVEL=0" + "CFG_TEE_CORE_LOG_LEVEL=0" + "CROSS_COMPILE=${toolchain}/bin/${toolchain.targetPrefix}" + "CROSS_COMPILE64=${toolchain}/bin/${toolchain.targetPrefix}" + ]; + + installPhase = '' + mkdir -p $out + cp ./out/arm-plat-imx/core/tee-raw.bin $out/tee.bin + ''; + + meta = { + homepage = "https://github.com/nxp-imx/imx-optee-os"; + license = [ lib.licenses.bsd2 ]; + platforms = [ "aarch64-linux" ]; + } + // meta; +} diff --git a/nxp/common/bsp/imx-uboot-builder.nix b/nxp/common/bsp/imx-uboot-builder.nix new file mode 100644 index 00000000..87bb7c22 --- /dev/null +++ b/nxp/common/bsp/imx-uboot-builder.nix @@ -0,0 +1,98 @@ +# Parameterized U-Boot builder for i.MX platforms +# This builder is used across i.MX93, i.MX8MP, i.MX8MQ and similar platforms +{ + lib, + stdenv, + buildPackages, + # Required dependencies + bison, + dtc, + flex, + gnutls, + libuuid, + ncurses, + openssl, + perl, + efitools, + which, + # Platform-specific parameters + pname, + version, + src, + defconfig, + ramdiskAddr, + fdtAddr, + dtbPath, + # Optional parameters + extraConfig ? "", + extraNativeBuildInputs ? [ ], +}: +let + # Import common U-Boot configuration + ubootConfig = import ../lib/uboot-config.nix; + + # Generate the common config with platform-specific memory addresses + commonConfig = ubootConfig.imxCommonUbootConfig { + inherit ramdiskAddr fdtAddr; + }; + + # Combine common config with any platform-specific extra config + finalExtraConfig = commonConfig + extraConfig; +in +stdenv.mkDerivation { + inherit pname version src; + + postPatch = '' + patchShebangs tools + patchShebangs scripts + ''; + + nativeBuildInputs = [ + bison + flex + openssl + which + ncurses + libuuid + gnutls + perl + efitools + ] + ++ extraNativeBuildInputs; + + depsBuildBuild = [ buildPackages.stdenv.cc ]; + hardeningDisable = [ "all" ]; + enableParallelBuilding = true; + + makeFlags = [ + "DTC=${lib.getExe buildPackages.dtc}" + "CROSS_COMPILE=${stdenv.cc.targetPrefix}" + ]; + + extraConfig = finalExtraConfig; + + passAsFile = [ "extraConfig" ]; + + configurePhase = '' + runHook preConfigure + + make ${defconfig} + cat $extraConfigPath >> .config + + runHook postConfigure + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out + cp ./u-boot-nodtb.bin $out + cp ./spl/u-boot-spl.bin $out + cp ${dtbPath} $out + cp .config $out + + runHook postInstall + ''; + + dontStrip = true; +} diff --git a/nxp/common/lib/kernel-config.nix b/nxp/common/lib/kernel-config.nix new file mode 100644 index 00000000..aca1e70c --- /dev/null +++ b/nxp/common/lib/kernel-config.nix @@ -0,0 +1,29 @@ +# Shared kernel configuration for i.MX platforms +# This configuration is used across i.MX93, i.MX8MP, i.MX8MQ and similar platforms +{ + # Common kernel extra configuration for i.MX platforms + # Includes: virtualization support, EFI boot, RAID, USB/IP, framebuffer settings + imxCommonKernelConfig = '' + CRYPTO_TLS m + TLS y + MD_RAID0 m + MD_RAID1 m + MD_RAID10 m + MD_RAID456 m + DM_VERITY m + LOGO y + FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER n + FB_EFI n + EFI_STUB y + EFI y + VIRTIO y + VIRTIO_PCI y + VIRTIO_BLK y + DRM_VIRTIO_GPU y + EXT4_FS y + USBIP_CORE m + USBIP_VHCI_HCD m + USBIP_HOST m + USBIP_VUDC m + ''; +} diff --git a/nxp/common/lib/uboot-config.nix b/nxp/common/lib/uboot-config.nix new file mode 100644 index 00000000..401e81c7 --- /dev/null +++ b/nxp/common/lib/uboot-config.nix @@ -0,0 +1,33 @@ +# Shared U-Boot configuration for i.MX platforms +# This configuration is used across i.MX93, i.MX8MP, i.MX8MQ and similar platforms +{ + # Generate common U-Boot extra configuration for i.MX platforms + # ramdiskAddr and fdtAddr are platform-specific memory addresses + imxCommonUbootConfig = + { ramdiskAddr, fdtAddr }: + '' + CONFIG_USE_BOOTCOMMAND=y + CONFIG_BOOTCOMMAND="setenv ramdisk_addr_r ${ramdiskAddr}; setenv fdt_addr_r ${fdtAddr}; run distro_bootcmd; " + CONFIG_CMD_BOOTEFI_SELFTEST=y + CONFIG_CMD_BOOTEFI=y + CONFIG_EFI_LOADER=y + CONFIG_BLK=y + CONFIG_PARTITIONS=y + CONFIG_DM_DEVICE_REMOVE=n + CONFIG_CMD_CACHE=y + ''; + + # Common U-Boot native build inputs for i.MX platforms + imxCommonUbootNativeBuildInputs = [ + "bison" + "flex" + "openssl" + "which" + "ncurses" + "libuuid" + "gnutls" + "openssl" + "perl" + "efitools" + ]; +} diff --git a/nxp/imx8mp-evk/bsp/imx8mp-linux.nix b/nxp/imx8mp-evk/bsp/imx8mp-linux.nix index 86025f2a..51522375 100644 --- a/nxp/imx8mp-evk/bsp/imx8mp-linux.nix +++ b/nxp/imx8mp-evk/bsp/imx8mp-linux.nix @@ -1,56 +1,20 @@ { pkgs, ... }@args: -with pkgs; -buildLinux ( - args - // rec { - version = "6.12.20"; - name = "imx8mp-linux"; +(pkgs.callPackage ../../common/bsp/imx-linux-builder.nix args) { + pname = "imx8mp-linux"; + version = "6.12.20"; - # modDirVersion needs to be x.y.z, will automatically add .0 if needed - modDirVersion = version; + src = pkgs.fetchFromGitHub { + owner = "nxp-imx"; + repo = "linux-imx"; + # tag: lf-6.12.20-2.0.0 + rev = "dfaf2136deb2af2e60b994421281ba42f1c087e0"; + sha256 = "sha256-ITrmj3a5YfXh/PSRTi+Rlto5uEBIAWFWtkTsO1ATXIo="; + }; - defconfig = "imx_v8_defconfig"; + # Platform-specific configuration (if any) + extraConfig = ""; - # https://github.com/NixOS/nixpkgs/pull/366004 - # introduced a breaking change that if a module is declared but it is not being used it will faill. - ignoreConfigErrors = true; - - kernelPatches = [ - ]; - - autoModules = false; - - extraConfig = '' - CRYPTO_TLS m - TLS y - MD_RAID0 m - MD_RAID1 m - MD_RAID10 m - MD_RAID456 m - DM_VERITY m - LOGO y - FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER n - FB_EFI n - EFI_STUB y - EFI y - VIRTIO y - VIRTIO_PCI y - VIRTIO_BLK y - DRM_VIRTIO_GPU y - EXT4_FS y - USBIP_CORE m - USBIP_VHCI_HCD m - USBIP_HOST m - USBIP_VUDC m - ''; - - src = fetchFromGitHub { - owner = "nxp-imx"; - repo = "linux-imx"; - # tag: lf-6.12.20-2.0.0 - rev = "dfaf2136deb2af2e60b994421281ba42f1c087e0"; - sha256 = "sha256-ITrmj3a5YfXh/PSRTi+Rlto5uEBIAWFWtkTsO1ATXIo="; - }; - } - // (args.argsOverride or { }) -) + # https://github.com/NixOS/nixpkgs/pull/366004 + # introduced a breaking change that if a module is declared but it is not being used it will faill. + ignoreConfigErrors = true; +} diff --git a/nxp/imx8mp-evk/bsp/imx8mp-optee-os.nix b/nxp/imx8mp-evk/bsp/imx8mp-optee-os.nix index 4cdd5f5d..c409e6c9 100644 --- a/nxp/imx8mp-evk/bsp/imx8mp-optee-os.nix +++ b/nxp/imx8mp-evk/bsp/imx8mp-optee-os.nix @@ -1,69 +1,13 @@ { pkgs }: -let - inherit (pkgs.buildPackages) python3; - toolchain = pkgs.gccStdenv.cc; - binutils = pkgs.gccStdenv.cc.bintools.bintools_bin; - cpp = pkgs.gcc; -in -pkgs.stdenv.mkDerivation rec { +pkgs.callPackage ../../common/bsp/imx-optee-builder.nix { pname = "imx8mp-optee-os"; version = "lf-6.12.20-2.0.0"; - nativeBuildInputs = [ - python3 - ]; - - enableParallelBuilding = true; - - propagatedBuildInputs = with python3.pkgs; [ - pycryptodomex - pyelftools - cryptography - ]; - src = pkgs.fetchgit { url = "https://github.com/nxp-imx/imx-optee-os.git"; rev = "87964807d80baf1dcfd89cafc66de34a1cf16bf3"; sha256 = "sha256-AMZUMgmmyi5l3BMT84uubwjU0lwNObs9XW6ZCbqfhmc="; }; - postPatch = '' - substituteInPlace scripts/arm32_sysreg.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace scripts/gen_tee_bin.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace scripts/pem_to_pub_c.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace ta/pkcs11/scripts/verify-helpers.sh \ - --replace '/usr/bin/env bash' '${pkgs.bash}/bin/bash' - substituteInPlace ta/pkcs11/scripts/dump_ec_curve_params.sh \ - --replace '/usr/bin/env bash' '${pkgs.bash}/bin/bash' - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))objcopy" ${binutils}/bin/${toolchain.targetPrefix}objcopy - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))objdump" ${binutils}/bin/${toolchain.targetPrefix}objdump - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))nm" ${binutils}/bin/${toolchain.targetPrefix}nm - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))readelf" ${binutils}/bin/${toolchain.targetPrefix}readelf - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))ar" ${binutils}/bin/${toolchain.targetPrefix}ar - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))cpp" ${cpp}/bin/cpp - ''; - - makeFlags = [ - "PLATFORM=imx" - "PLATFORM_FLAVOR=mx8mpevk" - "CFG_ARM64_core=y" - "CFG_TEE_TA_LOG_LEVEL=0" - "CFG_TEE_CORE_LOG_LEVEL=0" - "CROSS_COMPILE=${toolchain}/bin/${toolchain.targetPrefix}" - "CROSS_COMPILE64=${toolchain}/bin/${toolchain.targetPrefix}" - ]; - - installPhase = '' - mkdir -p $out - cp ./out/arm-plat-imx/core/tee-raw.bin $out/tee.bin - ''; + platformFlavor = "mx8mpevk"; } diff --git a/nxp/imx8mp-evk/bsp/imx8mp-uboot.nix b/nxp/imx8mp-evk/bsp/imx8mp-uboot.nix index 582cb70b..70b9992e 100644 --- a/nxp/imx8mp-evk/bsp/imx8mp-uboot.nix +++ b/nxp/imx8mp-evk/bsp/imx8mp-uboot.nix @@ -1,93 +1,17 @@ -{ - stdenv, - lib, - bison, - dtc, - fetchgit, - flex, - gnutls, - libuuid, - ncurses, - openssl, - which, - perl, - buildPackages, - efitools, -}: -let - ubsrc = fetchgit { +{ pkgs, fetchgit }: +pkgs.callPackage ../../common/bsp/imx-uboot-builder.nix { + pname = "imx8mp-uboot"; + version = "2025.04"; + + src = fetchgit { url = "https://github.com/nxp-imx/uboot-imx.git"; # tag: lf-6.12.20-2.0.0 rev = "9383f8387dc76524524da69992db96c22195a57c"; sha256 = "sha256-httRSwN8NiKOdL7fZEvN/4AbypGQfegYtJgxKIea+Zg="; }; -in -stdenv.mkDerivation { - pname = "imx8mp-uboot"; - version = "2025.04"; - src = ubsrc; - postPatch = '' - patchShebangs tools - patchShebangs scripts - ''; - - nativeBuildInputs = [ - bison - flex - openssl - which - ncurses - libuuid - gnutls - openssl - perl - efitools - ]; - - depsBuildBuild = [ buildPackages.stdenv.cc ]; - hardeningDisable = [ "all" ]; - enableParallelBuilding = true; - - makeFlags = [ - "DTC=${lib.getExe buildPackages.dtc}" - "CROSS_COMPILE=${stdenv.cc.targetPrefix}" - ]; - - extraConfig = '' - CONFIG_USE_BOOTCOMMAND=y - CONFIG_BOOTCOMMAND="setenv ramdisk_addr_r 0x45000000; setenv fdt_addr_r 0x44000000; run distro_bootcmd; " - CONFIG_CMD_BOOTEFI_SELFTEST=y - CONFIG_CMD_BOOTEFI=y - CONFIG_EFI_LOADER=y - CONFIG_BLK=y - CONFIG_PARTITIONS=y - CONFIG_DM_DEVICE_REMOVE=n - CONFIG_CMD_CACHE=y - ''; - - passAsFile = [ "extraConfig" ]; - - configurePhase = '' - runHook preConfigure - - make imx8mp_evk_defconfig - cat $extraConfigPath >> .config - - runHook postConfigure - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out - cp ./u-boot-nodtb.bin $out - cp ./spl/u-boot-spl.bin $out - cp ./dts/upstream/src/arm64/freescale/imx8mp-evk.dtb $out - cp .config $out - - runHook postInstall - ''; - - dontStrip = true; + defconfig = "imx8mp_evk_defconfig"; + ramdiskAddr = "0x45000000"; + fdtAddr = "0x44000000"; + dtbPath = "./dts/upstream/src/arm64/freescale/imx8mp-evk.dtb"; } diff --git a/nxp/imx8mq-evk/bsp/imx8mq-linux.nix b/nxp/imx8mq-evk/bsp/imx8mq-linux.nix index 5c2fb535..68d5d973 100644 --- a/nxp/imx8mq-evk/bsp/imx8mq-linux.nix +++ b/nxp/imx8mq-evk/bsp/imx8mq-linux.nix @@ -1,56 +1,20 @@ { pkgs, ... }@args: -with pkgs; -buildLinux ( - args - // rec { - version = "6.1.55"; - name = "imx8mq-linux"; +(pkgs.callPackage ../../common/bsp/imx-linux-builder.nix args) { + pname = "imx8mq-linux"; + version = "6.1.55"; - # modDirVersion needs to be x.y.z, will automatically add .0 if needed - modDirVersion = version; + src = pkgs.fetchFromGitHub { + owner = "nxp-imx"; + repo = "linux-imx"; + # tag: lf-6.1.55-2.2.0 + rev = "770c5fe2c1d1529fae21b7043911cd50c6cf087e"; + sha256 = "sha256-tIWt75RUrjB6KmUuAYBVyAC1dmVGSUAgqV5ROJh3xU0="; + }; - defconfig = "imx_v8_defconfig"; + # Platform-specific configuration (if any) + extraConfig = ""; - # https://github.com/NixOS/nixpkgs/pull/366004 - # introduced a breaking change that if a module is declared but it is not being used it will faill. - ignoreConfigErrors = true; - - kernelPatches = [ - ]; - - autoModules = false; - - extraConfig = '' - CRYPTO_TLS m - TLS y - MD_RAID0 m - MD_RAID1 m - MD_RAID10 m - MD_RAID456 m - DM_VERITY m - LOGO y - FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER n - FB_EFI n - EFI_STUB y - EFI y - VIRTIO y - VIRTIO_PCI y - VIRTIO_BLK y - DRM_VIRTIO_GPU y - EXT4_FS y - USBIP_CORE m - USBIP_VHCI_HCD m - USBIP_HOST m - USBIP_VUDC m - ''; - - src = fetchFromGitHub { - owner = "nxp-imx"; - repo = "linux-imx"; - # tag: lf-6.1.55-2.2.0 - rev = "770c5fe2c1d1529fae21b7043911cd50c6cf087e"; - sha256 = "sha256-tIWt75RUrjB6KmUuAYBVyAC1dmVGSUAgqV5ROJh3xU0="; - }; - } - // (args.argsOverride or { }) -) + # https://github.com/NixOS/nixpkgs/pull/366004 + # introduced a breaking change that if a module is declared but it is not being used it will faill. + ignoreConfigErrors = true; +} diff --git a/nxp/imx8mq-evk/bsp/imx8mq-optee-os.nix b/nxp/imx8mq-evk/bsp/imx8mq-optee-os.nix index 73b60a35..3762887c 100644 --- a/nxp/imx8mq-evk/bsp/imx8mq-optee-os.nix +++ b/nxp/imx8mq-evk/bsp/imx8mq-optee-os.nix @@ -1,67 +1,13 @@ { pkgs }: -let - python3 = pkgs.buildPackages.python3; - toolchain = pkgs.gcc9Stdenv.cc; - binutils = pkgs.gcc9Stdenv.cc.bintools.bintools_bin; - cpp = pkgs.gcc; -in -pkgs.stdenv.mkDerivation rec { +pkgs.callPackage ../../common/bsp/imx-optee-builder.nix { pname = "imx8mq-optee-os"; version = "lf-6.1.55-2.2.0"; - nativeBuildInputs = [ - python3 - ]; - - enableParallelBuilding = true; - - propagatedBuildInputs = with python3.pkgs; [ - pycryptodomex - pyelftools - cryptography - ]; - src = pkgs.fetchgit { url = "https://github.com/nxp-imx/imx-optee-os.git"; rev = "a303fc80f7c4bd713315687a1fa1d6ed136e78ee"; sha256 = "sha256-OpyG812DX0c06bRZPKWB2cNu6gtZCOvewDhsKgrGB+s="; }; - postPatch = '' - substituteInPlace scripts/arm32_sysreg.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace scripts/gen_tee_bin.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace scripts/pem_to_pub_c.py \ - --replace '/usr/bin/env python3' '${python3}/bin/python' - substituteInPlace ta/pkcs11/scripts/verify-helpers.sh \ - --replace '/bin/bash' '${pkgs.bash}/bin/bash' - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))objcopy" ${binutils}/bin/${toolchain.targetPrefix}objcopy - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))objdump" ${binutils}/bin/${toolchain.targetPrefix}objdump - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))nm" ${binutils}/bin/${toolchain.targetPrefix}nm - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))readelf" ${binutils}/bin/${toolchain.targetPrefix}readelf - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))ar" ${binutils}/bin/${toolchain.targetPrefix}ar - substituteInPlace mk/gcc.mk \ - --replace "\$(CROSS_COMPILE_\$(sm))cpp" ${cpp}/bin/cpp - ''; - - makeFlags = [ - "PLATFORM=imx" - "PLATFORM_FLAVOR=mx8mqevk" - "CFG_ARM64_core=y" - "CFG_TEE_TA_LOG_LEVEL=0" - "CFG_TEE_CORE_LOG_LEVEL=0" - "CROSS_COMPILE=${toolchain}/bin/${toolchain.targetPrefix}" - "CROSS_COMPILE64=${toolchain}/bin/${toolchain.targetPrefix}" - ]; - - installPhase = '' - mkdir -p $out - cp ./out/arm-plat-imx/core/tee-raw.bin $out/tee.bin - ''; + platformFlavor = "mx8mqevk"; } diff --git a/nxp/imx8mq-evk/bsp/imx8mq-uboot.nix b/nxp/imx8mq-evk/bsp/imx8mq-uboot.nix index 7bb9c2df..9acc1ee4 100644 --- a/nxp/imx8mq-evk/bsp/imx8mq-uboot.nix +++ b/nxp/imx8mq-evk/bsp/imx8mq-uboot.nix @@ -1,91 +1,17 @@ -{ - stdenv, - lib, - bison, - dtc, - fetchgit, - flex, - gnutls, - libuuid, - ncurses, - openssl, - which, - perl, - buildPackages, -}: -let - ubsrc = fetchgit { +{ pkgs, fetchgit }: +pkgs.callPackage ../../common/bsp/imx-uboot-builder.nix { + pname = "imx8mq-uboot"; + version = "2023.04"; + + src = fetchgit { url = "https://github.com/nxp-imx/uboot-imx.git"; # tag: "lf-6.1.55-2.2.0" rev = "49b102d98881fc28af6e0a8af5ea2186c1d90a5f"; sha256 = "sha256-1j6X82DqezEizeWoSS600XKPNwrQ4yT0vZuUImKAVVA="; }; -in -(stdenv.mkDerivation { - pname = "imx8mq-uboot"; - version = "2023.04"; - src = ubsrc; - postPatch = '' - patchShebangs tools - patchShebangs scripts - ''; - - nativeBuildInputs = [ - bison - flex - openssl - which - ncurses - libuuid - gnutls - openssl - perl - ]; - - depsBuildBuild = [ buildPackages.stdenv.cc ]; - hardeningDisable = [ "all" ]; - enableParallelBuilding = true; - - makeFlags = [ - "DTC=${lib.getExe buildPackages.dtc}" - "CROSS_COMPILE=${stdenv.cc.targetPrefix}" - ]; - - extraConfig = '' - CONFIG_USE_BOOTCOMMAND=y - CONFIG_BOOTCOMMAND="setenv ramdisk_addr_r 0x45000000; setenv fdt_addr_r 0x44000000; run distro_bootcmd; " - CONFIG_CMD_BOOTEFI_SELFTEST=y - CONFIG_CMD_BOOTEFI=y - CONFIG_EFI_LOADER=y - CONFIG_BLK=y - CONFIG_PARTITIONS=y - CONFIG_DM_DEVICE_REMOVE=n - CONFIG_CMD_CACHE=y - ''; - - passAsFile = [ "extraConfig" ]; - - configurePhase = '' - runHook preConfigure - - make imx8mq_evk_defconfig - cat $extraConfigPath >> .config - - runHook postConfigure - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out - cp ./u-boot-nodtb.bin $out - cp ./spl/u-boot-spl.bin $out - cp ./arch/arm/dts/imx8mq-evk.dtb $out - cp .config $out - - runHook postInstall - ''; - - dontStrip = true; -}) + defconfig = "imx8mq_evk_defconfig"; + ramdiskAddr = "0x45000000"; + fdtAddr = "0x44000000"; + dtbPath = "./arch/arm/dts/imx8mq-evk.dtb"; +} diff --git a/nxp/imx93-evk/bsp/imx93-atf.nix b/nxp/imx93-evk/bsp/imx93-atf.nix new file mode 100644 index 00000000..634cca19 --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-atf.nix @@ -0,0 +1,57 @@ +{ + lib, + fetchgit, + stdenv, + buildPackages, + pkgsCross, + openssl, +}: + +let + target-board = "imx93"; +in +stdenv.mkDerivation rec { + pname = "imx93-atf"; + version = "2.10.0"; + platform = target-board; + enableParallelBuilding = true; + + src = fetchgit { + url = "https://github.com/nxp-imx/imx-atf.git"; + rev = "28affcae957cb8194917b5246276630f9e6343e1"; + sha256 = "sha256-a8F+Lf8pwML+tCwawS0N/mrSXWPmFhlUeOg0MCRK3VE="; + }; + + # Compiler dependencies + depsBuildBuild = [ buildPackages.stdenv.cc ]; + nativeBuildInputs = [ pkgsCross.aarch64-embedded.stdenv.cc ]; + + buildInputs = [ openssl ]; + + makeFlags = [ + "HOSTCC=$(CC_FOR_BUILD)" + "CROSS_COMPILE=${pkgsCross.aarch64-embedded.stdenv.cc.targetPrefix}" + "PLAT=${platform}" + "SPD=opteed" + "bl31" + "LDFLAGS=-no-warn-rwx-segments" + ]; + + installPhase = '' + runHook preInstall + mkdir -p $out + cp build/${target-board}/release/bl31.bin $out + runHook postInstall + ''; + + hardeningDisable = [ "all" ]; + dontStrip = true; + + meta = with lib; { + homepage = "https://github.com/nxp-imx/imx-atf"; + description = "Reference implementation of secure world software for ARMv8-A"; + license = [ licenses.bsd3 ]; + maintainers = with maintainers; [ govindsi ]; + platforms = [ "aarch64-linux" ]; + }; +} diff --git a/nxp/imx93-evk/bsp/imx93-boot.nix b/nxp/imx93-evk/bsp/imx93-boot.nix new file mode 100644 index 00000000..c11f31d5 --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-boot.nix @@ -0,0 +1,84 @@ +{ + pkgs, +}: +with pkgs; +let + + imx93-atf = pkgs.callPackage ./imx93-atf.nix { }; + imx93-firmware = pkgs.callPackage ./imx93-firmware.nix { }; + imx93-uboot = pkgs.callPackage ./imx93-uboot.nix { }; + imx93-optee-os = pkgs.callPackage ./imx93-optee-os.nix { }; + src = pkgs.fetchgit { + url = "https://github.com/nxp-imx/imx-mkimage.git"; + #tag: lf-6.12.3 + rev = "4622115cbc037f79039c4522faeced4aabea986b"; + sha256 = "sha256-2gz0GxlB3jwy8PC6+cP3+MpyUzqE1vDTw8nuxK6vo3g="; + }; + shortRev = builtins.substring 0 8 src.rev; +in +{ + imx93-boot = pkgs.stdenv.mkDerivation rec { + inherit src; + name = "imx93-mkimage"; + version = "lf-6.12.3"; + + postPatch = '' + substituteInPlace Makefile \ + --replace 'git rev-parse --short=8 HEAD' 'echo ${shortRev}' + substituteInPlace Makefile \ + --replace 'CC = gcc' 'CC = clang' + substituteInPlace iMX93/soc.mak \ + --replace 'xxd' "${pkgs.vim.xxd}/bin/xxd" + substituteInPlace scripts/fspi_fcb_gen.sh \ + --replace 'xxd' "${pkgs.vim.xxd}/bin/xxd" + substituteInPlace scripts/fspi_packer.sh \ + --replace 'xxd' "${pkgs.vim.xxd}/bin/xxd" + patchShebangs scripts + ''; + + nativeBuildInputs = [ + clang + git + dtc + ]; + + buildInputs = [ + git + glibc.static + zlib + zlib.static + ]; + + buildPhase = '' + runHook preBuild + + make bin + # mkimage is common across imx8 and imx9 + make SOC=iMX8M mkimage_imx8 + + if [ -f ${imx93-uboot}/u-boot.bin ]; then + install -m 0644 ${imx93-uboot}/u-boot.bin ./iMX93/u-boot.bin + else + cat ${imx93-uboot}/u-boot-nodtb.bin ${imx93-uboot}/imx93-11x11-evk.dtb > ./iMX93/u-boot.bin + fi + install -m 0644 ${imx93-uboot}/u-boot-spl.bin ./iMX93/u-boot-spl.bin + install -m 0644 ${imx93-uboot}/u-boot-nodtb.bin ./iMX93/u-boot-nodtb.bin + install -m 0644 ${imx93-uboot}/imx93-11x11-evk.dtb ./iMX93/imx93-11x11-evk.dtb + install -m 0644 ${imx93-optee-os}/tee.bin ./iMX93/tee.bin + install -m 0644 ${imx93-atf}/bl31.bin ./iMX93/bl31.bin + install -m 0644 ${imx93-firmware}/ddr/lpddr4* ./iMX93/ + install -m 0644 ${imx93-firmware}/ahab/mx93a1-ahab-container.img ./iMX93/ + + make SOC=iMX9 flash_singleboot + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out/image + install -m 0644 ./iMX93/flash.bin $out/image + runHook postInstall + ''; + }; +} diff --git a/nxp/imx93-evk/bsp/imx93-firmware.nix b/nxp/imx93-evk/bsp/imx93-firmware.nix new file mode 100644 index 00000000..1caa2392 --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-firmware.nix @@ -0,0 +1,48 @@ +{ pkgs, ... }: + +with pkgs; +stdenv.mkDerivation rec { + pname = "nxp-firmware"; + version = "nxp-firmware-8.21-0.11"; + + ddrFirmware = fetchurl { + url = "https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.21.bin"; + sha256 = "sha256-w0R/D4E0FczqncLvEggMs6yLvAxnOSp0/H1ZIF61pnI="; + }; + + ahabFirmware = fetchurl { + url = "https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-sentinel-0.11.bin"; + sha256 = "sha256-JpSAQXqK6apMxBAauUcof8M0VakxAh29xNm621ISvOs="; + }; + + nativeBuildInputs = [ + coreutils + bash + ]; + + dontUnpack = true; + dontStrip = true; + + installPhase = '' + mkdir -p $out + + echo "Extracting DDR firmware..." + cp ${ddrFirmware} ./firmware-imx-8.21.bin + chmod +x firmware-imx-8.21.bin + ./firmware-imx-8.21.bin --auto-accept + + echo "Extracting AHAB firmware..." + cp ${ahabFirmware} ./firmware-sentinel-0.11.bin + chmod +x firmware-sentinel-0.11.bin + ./firmware-sentinel-0.11.bin --auto-accept + + echo "Copying DDR .bin files..." + mkdir -p $out/ddr + cp firmware-imx-8.21/firmware/ddr/synopsys/lpddr4*.bin $out/ddr/ + + echo "Copying AHAB container image..." + mkdir -p $out/ahab + cp firmware-sentinel-0.11/mx93a1-ahab-container.img $out/ahab/ + + ''; +} diff --git a/nxp/imx93-evk/bsp/imx93-linux.nix b/nxp/imx93-evk/bsp/imx93-linux.nix new file mode 100644 index 00000000..1bdb8332 --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-linux.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }@args: +(pkgs.callPackage ../../common/bsp/imx-linux-builder.nix args) { + pname = "imx93-linux"; + version = "6.12.3"; + + src = pkgs.fetchFromGitHub { + owner = "nxp-imx"; + repo = "linux-imx"; + # tag: lf-6.12.3 + rev = "37d02f4dcbbe6677dc9f5fc17f386c05d6a7bd7a"; + sha256 = "sha256-1oJMbHR8Ho0zNritEJ+TMOAyYHCW0vwhPkDfLctrZa8="; + }; + + # Platform-specific configuration (if any) + extraConfig = ""; + + # https://github.com/NixOS/nixpkgs/pull/366004 + # introduced a breaking change that if a module is declared but it is not being used it will faill. + ignoreConfigErrors = true; + + extraMeta = { + maintainers = with pkgs.lib.maintainers; [ govindsi ]; + }; +} diff --git a/nxp/imx93-evk/bsp/imx93-optee-os.nix b/nxp/imx93-evk/bsp/imx93-optee-os.nix new file mode 100644 index 00000000..a48a5bec --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-optee-os.nix @@ -0,0 +1,17 @@ +{ pkgs }: +pkgs.callPackage ../../common/bsp/imx-optee-builder.nix { + pname = "imx93-optee-os"; + version = "lf-6.12.3_1.0.0"; + + src = pkgs.fetchgit { + url = "https://github.com/nxp-imx/imx-optee-os.git"; + rev = "8dd180b6d149c1e1314b5869697179f665bd9ca3"; + sha256 = "sha256-PoolRscdyeGevrOa5YymPTQ36edVvReMM5WshRTz+uk="; + }; + + platformFlavor = "imx-mx93evk"; + + meta = { + maintainers = with pkgs.lib.maintainers; [ govindsi ]; + }; +} diff --git a/nxp/imx93-evk/bsp/imx93-uboot.nix b/nxp/imx93-evk/bsp/imx93-uboot.nix new file mode 100644 index 00000000..9c6f6f9f --- /dev/null +++ b/nxp/imx93-evk/bsp/imx93-uboot.nix @@ -0,0 +1,17 @@ +{ pkgs, fetchgit }: +pkgs.callPackage ../../common/bsp/imx-uboot-builder.nix { + pname = "imx93-uboot"; + version = "2024.04"; + + src = fetchgit { + url = "https://github.com/nxp-imx/uboot-imx.git"; + #lf_v2024.04 + rev = "e3219a5a73445219df605d1492687918d488055c"; + sha256 = "sha256-6pXwgNzq4/XUUEmJ6sGC5pII4J5uMvlDPE9QJxjJJbQ="; + }; + + defconfig = "imx93_11x11_evk_defconfig"; + ramdiskAddr = "0x85000000"; + fdtAddr = "0x84000000"; + dtbPath = "./arch/arm/dts/imx93-11x11-evk.dtb"; +} diff --git a/nxp/imx93-evk/default.nix b/nxp/imx93-evk/default.nix new file mode 100644 index 00000000..fd375aa4 --- /dev/null +++ b/nxp/imx93-evk/default.nix @@ -0,0 +1,21 @@ +{ pkgs, ... }: +{ + nixpkgs.overlays = [ + (import ./overlay.nix) + ]; + + imports = [ + ./modules.nix + ]; + + boot.loader.grub.extraFiles = { + "imx93-11x11-evk.dtb" = "${ + pkgs.callPackage ./bsp/imx93-linux.nix { } + }/dtbs/freescale/imx93-11x11-evk.dtb"; + }; + + hardware.deviceTree = { + filter = "imx93-*.dtb"; + name = "imx93-11x11-evk.dtb"; + }; +} diff --git a/nxp/imx93-evk/modules.nix b/nxp/imx93-evk/modules.nix new file mode 100644 index 00000000..b8939684 --- /dev/null +++ b/nxp/imx93-evk/modules.nix @@ -0,0 +1,17 @@ +{ + pkgs, + lib, + ... +}: +{ + nixpkgs.hostPlatform = "aarch64-linux"; + + boot = { + kernelPackages = pkgs.linuxPackagesFor (pkgs.callPackage ./bsp/imx93-linux.nix { }); + initrd.includeDefaultModules = lib.mkForce false; + }; + + disabledModules = [ "profiles/all-hardware.nix" ]; + + hardware.deviceTree.enable = true; +} diff --git a/nxp/imx93-evk/overlay.nix b/nxp/imx93-evk/overlay.nix new file mode 100644 index 00000000..420e974a --- /dev/null +++ b/nxp/imx93-evk/overlay.nix @@ -0,0 +1,3 @@ +final: _prev: { + inherit (final.callPackage ./bsp/imx93-boot.nix { pkgs = final; }) imx93-boot; +} diff --git a/pine64/star64/linux-5.15.nix b/pine64/star64/linux-5.15.nix index 28d9adbb..39d8cedc 100644 --- a/pine64/star64/linux-5.15.nix +++ b/pine64/star64/linux-5.15.nix @@ -45,7 +45,8 @@ let }; } { patch = ./irq-desc-to-data.patch; } - ] ++ kernelPatches; + ] + ++ kernelPatches; structuredExtraConfig = with lib.kernel; { # A ton of stuff just does not build. We disable it all. diff --git a/tests/flake-compat.nix b/tests/flake-compat.nix new file mode 100644 index 00000000..ddc1cd0e --- /dev/null +++ b/tests/flake-compat.nix @@ -0,0 +1,299 @@ +# Compatibility function to allow flakes to be used by +# non-flake-enabled Nix versions. Given a source tree containing a +# 'flake.nix' and 'flake.lock' file, it fetches the flake inputs and +# calls the flake's 'outputs' function. It then returns an attrset +# containing 'defaultNix' (to be used in 'default.nix'), 'shellNix' +# (to be used in 'shell.nix'). + +{ + src, + system ? builtins.currentSystem or "unknown-system", +}: + +let + + lockFilePath = src + "/flake.lock"; + + lockFile = builtins.fromJSON (builtins.readFile lockFilePath); + + fetchTree = + builtins.fetchTree or ( + info: + if info.type == "github" then + { + outPath = fetchTarball ( + { + url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}"; + } + // (if info ? narHash then { sha256 = info.narHash; } else { }) + ); + rev = info.rev; + shortRev = builtins.substring 0 7 info.rev; + lastModified = info.lastModified; + lastModifiedDate = formatSecondsSinceEpoch info.lastModified; + narHash = info.narHash; + } + else if info.type == "git" then + { + outPath = builtins.fetchGit ( + { + url = info.url; + } + // (if info ? rev then { inherit (info) rev; } else { }) + // (if info ? ref then { inherit (info) ref; } else { }) + // (if info ? submodules then { inherit (info) submodules; } else { }) + ); + lastModified = info.lastModified; + lastModifiedDate = formatSecondsSinceEpoch info.lastModified; + narHash = info.narHash; + revCount = info.revCount or 0; + } + // ( + if info ? rev then + { + rev = info.rev; + shortRev = builtins.substring 0 7 info.rev; + } + else + { } + ) + else if info.type == "path" then + { + outPath = builtins.path { + path = info.path; + sha256 = info.narHash; + }; + narHash = info.narHash; + } + else if info.type == "tarball" then + { + outPath = fetchTarball ( + { inherit (info) url; } // (if info ? narHash then { sha256 = info.narHash; } else { }) + ); + } + else if info.type == "gitlab" then + { + inherit (info) rev narHash lastModified; + outPath = fetchTarball ( + { + url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}"; + } + // (if info ? narHash then { sha256 = info.narHash; } else { }) + ); + shortRev = builtins.substring 0 7 info.rev; + } + else if info.type == "sourcehut" then + { + inherit (info) rev narHash lastModified; + outPath = fetchTarball ( + { + url = "https://${info.host or "git.sr.ht"}/${info.owner}/${info.repo}/archive/${info.rev}.tar.gz"; + } + // (if info ? narHash then { sha256 = info.narHash; } else { }) + ); + shortRev = builtins.substring 0 7 info.rev; + } + else + # FIXME: add Mercurial, tarball inputs. + throw "flake input has unsupported input type '${info.type}'" + ); + + callFlake4 = + flakeSrc: locks: + let + flake = import (flakeSrc + "/flake.nix"); + + inputs = builtins.mapAttrs ( + _n: v: + if v.flake or true then + callFlake4 (fetchTree (v.locked // v.info)) v.inputs + else + fetchTree (v.locked // v.info) + ) locks; + + outputs = flakeSrc // (flake.outputs (inputs // { self = outputs; })); + in + assert flake.edition == 201909; + outputs; + + callLocklessFlake = + flakeSrc: + let + flake = import (flakeSrc + "/flake.nix"); + outputs = flakeSrc // (flake.outputs ({ self = outputs; })); + in + outputs; + + rootSrc = + let + # Try to clean the source tree by using fetchGit, if this source + # tree is a valid git repository. + tryFetchGit = + src: + if isGit && !isShallow then + let + res = builtins.fetchGit src; + in + if res.rev == "0000000000000000000000000000000000000000" then + removeAttrs res [ + "rev" + "shortRev" + ] + else + res + else + { + outPath = + # Massage `src` into a store path. + if builtins.isPath src then + if + dirOf (toString src) == builtins.storeDir + # `builtins.storePath` is not available in pure-eval mode. + && builtins ? currentSystem + then + # If it's already a store path, don't copy it again. + builtins.storePath src + else + "${src}" + else + src; + }; + # NB git worktrees have a file for .git, so we don't check the type of .git + isGit = builtins.pathExists (src + "/.git"); + isShallow = builtins.pathExists (src + "/.git/shallow"); + + in + { + lastModified = 0; + lastModifiedDate = formatSecondsSinceEpoch 0; + } + // (if src ? outPath then src else tryFetchGit src); + + # Format number of seconds in the Unix epoch as %Y%m%d%H%M%S. + formatSecondsSinceEpoch = + t: + let + rem = x: y: x - x / y * y; + days = t / 86400; + secondsInDay = rem t 86400; + hours = secondsInDay / 3600; + minutes = (rem secondsInDay 3600) / 60; + seconds = rem t 60; + + # Courtesy of https://stackoverflow.com/a/32158604. + z = days + 719468; + era = (if z >= 0 then z else z - 146096) / 146097; + doe = z - era * 146097; + yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + y = yoe + era * 400; + doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + mp = (5 * doy + 2) / 153; + d = doy - (153 * mp + 2) / 5 + 1; + m = mp + (if mp < 10 then 3 else -9); + y' = y + (if m <= 2 then 1 else 0); + + pad = s: if builtins.stringLength s < 2 then "0" + s else s; + in + "${toString y'}${pad (toString m)}${pad (toString d)}${pad (toString hours)}${pad (toString minutes)}${pad (toString seconds)}"; + + allNodes = builtins.mapAttrs ( + key: node: + let + sourceInfo = + if key == lockFile.root then + rootSrc + else + fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]); + + subdir = if key == lockFile.root then "" else node.locked.dir or ""; + + outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir); + + flake = import (outPath + "/flake.nix"); + + inputs = builtins.mapAttrs (_inputName: inputSpec: allNodes.${resolveInput inputSpec}) ( + node.inputs or { } + ); + + # Resolve a input spec into a node name. An input spec is + # either a node name, or a 'follows' path from the root + # node. + resolveInput = + inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec; + + # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the + # root node, returning the final node. + getInputByPath = + nodeName: path: + if path == [ ] then + nodeName + else + getInputByPath + # Since this could be a 'follows' input, call resolveInput. + (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) + (builtins.tail path); + + outputs = flake.outputs (inputs // { self = result; }); + + result = + outputs + # We add the sourceInfo attribute for its metadata, as they are + # relevant metadata for the flake. However, the outPath of the + # sourceInfo does not necessarily match the outPath of the flake, + # as the flake may be in a subdirectory of a source. + # This is shadowed in the next // + // sourceInfo + // { + # This shadows the sourceInfo.outPath + inherit outPath; + + inherit inputs; + inherit outputs; + inherit sourceInfo; + _type = "flake"; + }; + + in + if node.flake or true then + assert builtins.isFunction flake.outputs; + result + else + sourceInfo + ) lockFile.nodes; + + result = + if !(builtins.pathExists lockFilePath) then + callLocklessFlake rootSrc + else if lockFile.version == 4 then + callFlake4 rootSrc (lockFile.inputs) + else if lockFile.version >= 5 && lockFile.version <= 7 then + allNodes.${lockFile.root} + else + throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}"; + +in +rec { + outputs = result; + + defaultNix = + builtins.removeAttrs result [ "__functor" ] + // ( + if result ? defaultPackage.${system} then { default = result.defaultPackage.${system}; } else { } + ) + // ( + if result ? packages.${system}.default then + { default = result.packages.${system}.default; } + else + { } + ); + + shellNix = + defaultNix + // (if result ? devShell.${system} then { default = result.devShell.${system}; } else { }) + // ( + if result ? devShells.${system}.default then + { default = result.devShells.${system}.default; } + else + { } + ); +} diff --git a/tests/flake.lock b/tests/flake.lock index 4363c6d1..da5ee417 100644 --- a/tests/flake.lock +++ b/tests/flake.lock @@ -1,78 +1,39 @@ { "nodes": { - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "nixos-unstable-small" - ] - }, - "locked": { - "lastModified": 1743550720, - "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "c621e8422220273271f52058f618c94e405bb0f5", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "nixos-hardware": { - "locked": { - "lastModified": 1747083103, - "narHash": "sha256-dMx20S2molwqJxbmMB4pGjNfgp5H1IOHNa1Eby6xL+0=", - "owner": "NixOS", - "repo": "nixos-hardware", - "rev": "d1d68fe8b00248caaa5b3bbe4984c12b47e0867d", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixos-hardware", - "type": "github" - } - }, "nixos-stable": { "locked": { - "lastModified": 1751211869, - "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=", - "ref": "nixos-25.05", - "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51", - "shallow": true, - "type": "git", - "url": "https://github.com/NixOS/nixpkgs" + "lastModified": 1755274400, + "narHash": "sha256-rTInmnp/xYrfcMZyFMH3kc8oko5zYfxsowaLv1LVobY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ad7196ae55c295f53a7d1ec39e4a06d922f3b899", + "type": "github" }, "original": { + "owner": "NixOS", "ref": "nixos-25.05", - "shallow": true, - "type": "git", - "url": "https://github.com/NixOS/nixpkgs" + "repo": "nixpkgs", + "type": "github" } }, "nixos-unstable-small": { "locked": { - "lastModified": 1747040834, - "narHash": "sha256-iKQKoNlZmxQq+O2WfImm/jn97g5GZBVW5EZEoCTXZ3I=", - "ref": "nixos-unstable-small", - "rev": "e4f52f3ea82ddd3754b467e3fdc0d709685c9a05", - "shallow": true, - "type": "git", - "url": "https://github.com/NixOS/nixpkgs" + "lastModified": 1755375481, + "narHash": "sha256-43PgCQFgFD1nM/7dncytV0c5heNHe/gXrEud18ZWcZU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "35f1742e4f1470817ff8203185e2ce0359947f12", + "type": "github" }, "original": { + "owner": "NixOS", "ref": "nixos-unstable-small", - "shallow": true, - "type": "git", - "url": "https://github.com/NixOS/nixpkgs" + "repo": "nixpkgs", + "type": "github" } }, "root": { "inputs": { - "flake-parts": "flake-parts", - "nixos-hardware": "nixos-hardware", "nixos-stable": "nixos-stable", "nixos-unstable-small": "nixos-unstable-small", "treefmt-nix": "treefmt-nix" diff --git a/tests/flake.nix b/tests/flake.nix index 443bfbd7..242c07be 100644 --- a/tests/flake.nix +++ b/tests/flake.nix @@ -1,127 +1,12 @@ { - description = "Test flake for nixos-hardware"; + description = "Private dev inputs for nixos-hardware"; inputs = { - nixos-unstable-small.url = "git+https://github.com/NixOS/nixpkgs?shallow=1&ref=nixos-unstable-small"; - nixos-stable.url = "git+https://github.com/NixOS/nixpkgs?shallow=1&ref=nixos-25.05"; - # override in the test - nixos-hardware.url = "github:NixOS/nixos-hardware"; - flake-parts.url = "github:hercules-ci/flake-parts"; - flake-parts.inputs.nixpkgs-lib.follows = "nixos-unstable-small"; + nixos-unstable-small.url = "github:NixOS/nixpkgs/nixos-unstable-small"; + nixos-stable.url = "github:NixOS/nixpkgs/nixos-25.05"; treefmt-nix.url = "github:numtide/treefmt-nix"; treefmt-nix.inputs.nixpkgs.follows = "nixos-unstable-small"; }; - outputs = - inputs@{ flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } { - imports = [ - inputs.treefmt-nix.flakeModule - ]; - systems = [ - "aarch64-linux" - "x86_64-linux" - "riscv64-linux" - ]; - perSystem = - { - system, - lib, - pkgs, - ... - }: - let - blackList = [ - # does import-from-derivation - "toshiba-swanky" - # uses custom nixpkgs config - "raspberry-pi-2" - - # deprecated profiles - "framework" - "asus-zephyrus-ga402x" - "lenovo-yoga-7-14ARH7" - ]; - - # There are more, but for those we need to force it. - # In future we should probably already define it in our module. - aarch64Systems = [ - "raspberry-pi-3" - "raspberry-pi-4" - "raspberry-pi-5" - ]; - - matchArch = - moduleName: - if builtins.elem moduleName aarch64Systems then - pkgs.hostPlatform.system == "aarch64-linux" - else - # TODO also add riscv64 - pkgs.hostPlatform.system == "x86_64-linux"; - - modules = lib.filterAttrs ( - name: _: !(builtins.elem name blackList || lib.hasPrefix "common-" name) && matchArch name - ) inputs.nixos-hardware.nixosModules; - buildProfile = import ./build-profile.nix; - - unfreeNixpkgs = - importPath: - import importPath { - config = { - allowBroken = true; - allowUnfree = true; - nvidia.acceptLicense = true; - }; - overlays = [ ]; - inherit system; - }; - nixpkgsUnstable = unfreeNixpkgs inputs.nixos-unstable-small; - nixpkgsStable = unfreeNixpkgs inputs.nixos-stable; - - checksForNixpkgs = - channel: nixpkgs: - lib.mapAttrs' ( - name: module: - lib.nameValuePair "${channel}-${name}" (buildProfile { - pkgs = nixpkgs; - profile = module; - }) - ) modules; - in - { - _module.args.pkgs = nixpkgsUnstable; - - treefmt = { - flakeCheck = pkgs.hostPlatform.system != "riscv64-linux"; - projectRootFile = "COPYING"; - programs = { - deadnix = { - enable = true; - no-lambda-pattern-names = true; - }; - nixfmt = { - enable = true; - package = pkgs.nixfmt-rfc-style; - }; - }; - settings = { - on-unmatched = "info"; - }; - }; - - checks = - checksForNixpkgs "nixos-unstable" nixpkgsUnstable - // checksForNixpkgs "nixos-stable" nixpkgsStable; - packages.run = pkgs.writeShellScriptBin "run.py" '' - #!${pkgs.bash}/bin/bash - export PATH=${ - lib.makeBinPath [ - pkgs.nix-eval-jobs - pkgs.nix-eval-jobs.nix - ] - } - exec ${pkgs.python3.interpreter} ${./.}/run.py --nixos-hardware "$@" - ''; - }; - }; + outputs = inputs: inputs; } diff --git a/tests/nixos-tests.nix b/tests/nixos-tests.nix new file mode 100644 index 00000000..0fcf6ed9 --- /dev/null +++ b/tests/nixos-tests.nix @@ -0,0 +1,70 @@ +{ + self, + privateInputs, + system, + pkgs, +}: +let + # Hardware profile checks + blackList = [ + # does import-from-derivation + "toshiba-swanky" + # uses custom nixpkgs config + "raspberry-pi-2" + # deprecated profiles + "framework" + "asus-zephyrus-ga402x" + "lenovo-yoga-7-14ARH7" + ]; + + aarch64Systems = [ + "raspberry-pi-3" + "raspberry-pi-4" + "raspberry-pi-5" + ]; + + matchArch = + moduleName: + if builtins.elem moduleName aarch64Systems then + system == "aarch64-linux" + else + # TODO also add riscv64 + system == "x86_64-linux"; + + modules = pkgs.lib.filterAttrs ( + name: _: !(builtins.elem name blackList || pkgs.lib.hasPrefix "common-" name) && matchArch name + ) self.nixosModules; + + buildProfile = import ./build-profile.nix; + + unfreeNixpkgs = { + config = { + allowBroken = true; + allowUnfree = true; + nvidia.acceptLicense = true; + }; + overlays = [ ]; + inherit system; + }; + + nixpkgsUnstable = import privateInputs.nixos-unstable-small unfreeNixpkgs; + nixpkgsStable = import privateInputs.nixos-stable unfreeNixpkgs; + + # Build checks for both unstable and stable + unstableChecks = pkgs.lib.mapAttrs' ( + name: module: + pkgs.lib.nameValuePair "unstable-${name}" (buildProfile { + pkgs = nixpkgsUnstable; + profile = module; + }) + ) modules; + + stableChecks = pkgs.lib.mapAttrs' ( + name: module: + pkgs.lib.nameValuePair "stable-${name}" (buildProfile { + pkgs = nixpkgsStable; + profile = module; + }) + ) modules; +in +unstableChecks // stableChecks diff --git a/tests/run-tests.nix b/tests/run-tests.nix new file mode 100644 index 00000000..a2606bbc --- /dev/null +++ b/tests/run-tests.nix @@ -0,0 +1,19 @@ +{ + lib, + writeShellScriptBin, + bash, + python3, + nix-eval-jobs, + self, +}: + +writeShellScriptBin "run-tests" '' + #!${bash}/bin/bash + export PATH=${ + lib.makeBinPath [ + nix-eval-jobs + nix-eval-jobs.nix + ] + } + exec ${python3.interpreter} ${self}/tests/run.py +'' diff --git a/tests/run.py b/tests/run.py index efe76b52..786e99bd 100755 --- a/tests/run.py +++ b/tests/run.py @@ -3,6 +3,7 @@ import argparse import json import multiprocessing +import os import shlex import subprocess import sys @@ -16,6 +17,37 @@ GREEN = "\033[92m" RED = "\033[91m" RESET = "\033[0m" +def is_github_actions() -> bool: + """Check if running in GitHub Actions environment.""" + return os.getenv("GITHUB_ACTIONS") == "true" + +def github_error(message: str, title: str = "") -> None: + """Output GitHub Actions error annotation.""" + if title: + print(f"::error title={title}::{message}") + else: + print(f"::error::{message}") + +def github_warning(message: str, title: str = "") -> None: + """Output GitHub Actions warning annotation.""" + if title: + print(f"::warning title={title}::{message}") + else: + print(f"::warning::{message}") + +def format_nix_error(error_text: str) -> str: + """Format nix evaluation error for better readability.""" + lines = error_text.strip().split('\n') + # Try to extract the most relevant error line + for line in lines: + if 'error:' in line.lower(): + return line.strip() + # If no specific error line found, return first non-empty line + for line in lines: + if line.strip(): + return line.strip() + return error_text.strip() + def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Run hardware tests") parser.add_argument( @@ -30,22 +62,15 @@ def parse_args() -> argparse.Namespace: action="store_true", help="Print evaluation commands executed", ) - parser.add_argument( - "--nixos-hardware", - help="Print evaluation commands executed", - ) return parser.parse_args() -def run_eval_test(nixos_hardware: str, gcroot_dir: Path, jobs: int) -> list[str]: +def run_eval_test(gcroot_dir: Path, jobs: int) -> list[str]: failed_profiles = [] cmd = [ "nix-eval-jobs", - "--extra-experimental-features", - "flakes", - "--override-input", - "nixos-hardware", - nixos_hardware, + "--extra-experimental-features", "flakes", + "--option", "eval-cache", "false", "--gc-roots-dir", str(gcroot_dir), "--max-memory-size", @@ -53,7 +78,7 @@ def run_eval_test(nixos_hardware: str, gcroot_dir: Path, jobs: int) -> list[str] "--workers", str(jobs), "--flake", - str(TEST_ROOT) + "#checks", + str(ROOT) + "#checks", "--force-recurse", ] print(" ".join(map(shlex.quote, cmd))) @@ -70,8 +95,19 @@ def run_eval_test(nixos_hardware: str, gcroot_dir: Path, jobs: int) -> list[str] attr = data.get("attr") if "error" in data: failed_profiles.append(attr) + error_msg = data['error'] + formatted_error = format_nix_error(error_msg) + + # Output for terminal print(f"{RED}FAIL {attr}:{RESET}", file=sys.stderr) - print(f"{RED}{data['error']}{RESET}", file=sys.stderr) + print(f"{RED}{error_msg}{RESET}", file=sys.stderr) + + # Output for GitHub Actions + if is_github_actions(): + github_error( + formatted_error, + title=f"Hardware profile evaluation failed: {attr}" + ) else: print(f"{GREEN}OK {attr}{RESET}") return failed_profiles @@ -84,12 +120,21 @@ def main() -> None: with TemporaryDirectory() as tmpdir: gcroot_dir = Path(tmpdir) / "gcroot" - failed_profiles = run_eval_test(args.nixos_hardware, gcroot_dir, args.jobs) + failed_profiles = run_eval_test(gcroot_dir, args.jobs) if len(failed_profiles) > 0: - print(f"\n{RED}The following {len(failed_profiles)} test(s) failed:{RESET}") + failure_msg = f"The following {len(failed_profiles)} test(s) failed:" + print(f"\n{RED}{failure_msg}{RESET}") for profile in failed_profiles: print(f" '{profile}'") + + # GitHub Actions summary + if is_github_actions(): + github_error( + f"{failure_msg} {', '.join(failed_profiles)}", + title="Hardware Profile Tests Failed" + ) + sys.exit(1) diff --git a/tests/treefmt.nix b/tests/treefmt.nix new file mode 100644 index 00000000..46df7f2b --- /dev/null +++ b/tests/treefmt.nix @@ -0,0 +1,11 @@ +{ + projectRootFile = "flake.nix"; + programs = { + deadnix = { + enable = true; + no-lambda-pattern-names = true; + }; + nixfmt.enable = true; + }; + settings.on-unmatched = "info"; +}