This commit is contained in:
mjallen18
2025-12-30 14:28:48 -06:00
parent b36ae0914c
commit b216fe5215
15 changed files with 667 additions and 59 deletions

View File

@@ -123,7 +123,7 @@ in
partitions = {
FIRMWARE = lib.mkIf cfg.enableFirmware {
priority = 1;
name = "FIRMWARE";
name = "${config.${namespace}.network.hostName}-FIRMWARE";
start = "1M";
end = "1G";
type = "0700";
@@ -138,6 +138,7 @@ in
priority = if cfg.enableFirmware then 2 else 1;
type = "EF00";
size = "500M";
name = "${config.${namespace}.network.hostName}-EFI";
content = {
type = "filesystem";
format = "vfat";

View File

@@ -179,6 +179,6 @@ in {
};
config = {
hardware.raspberry-pi.config-generated = render-raspberrypi-config cfg.config;
${namespace}.hardware.raspberry-pi.config-generated = render-raspberrypi-config cfg.config;
};
}

View File

@@ -12,6 +12,110 @@ let
applyOverlays = _final.callPackage ./apply-overlays-dtmerge.nix { };
};
};
ubootBinName = "u-boot.bin";
deviceTree = ({ pkgs
, firmware
}: pkgs.replaceVarsWith {
src = ./generational/install-device-tree.sh;
isExecutable = true;
replacements = {
inherit (pkgs) bash;
path = pkgs.lib.makeBinPath [
pkgs.coreutils
];
inherit firmware;
};
});
# installs raspberry's firmware independent of the nixos generations
# sometimes referred to as "boot code"
raspberryPiFirmware = ({ pkgs
, firmware
, configTxt
}: pkgs.replaceVarsWith {
src = ./generational/install-firmware.sh;
isExecutable = true;
replacements = {
inherit (pkgs) bash;
path = pkgs.lib.makeBinPath [
pkgs.coreutils
];
inherit firmware configTxt;
};
});
# Builders used to write during system activation
firmwareBuilder = import ./firmware-builder.nix {
inherit pkgs;
configTxt = pkgs.writeTextFile {
name = "config.txt";
text = ''
# Do not edit!
# This configuration file is generated from NixOS configuration
# options `hardware.raspberry-pi.config`.
# Any manual changes will be overwritten on the next configuration
# switch.
${config.${namespace}.hardware.raspberry-pi.config-generated}
'';
};
firmware = pkgs.${namespace}.raspberrypifw;
};
ubootBuilder = import ./uboot-builder.nix {
inherit pkgs;
ubootPackage = pkgs.${namespace}.uboot-pi5;
firmwareBuilder = firmwarePopulateCmd;
extlinuxConfBuilder = config.boot.loader.generic-extlinux-compatible.populateCmd;
};
# Builders exposed via populateCmd, which run on the build architecture
populateFirmwareBuilder = import ./firmware-builder.nix {
pkgs = pkgs.buildPackages;
configTxt = pkgs.writeTextFile {
name = "config.txt";
text = ''
# Do not edit!
# This configuration file is generated from NixOS configuration
# options `hardware.raspberry-pi.config`.
# Any manual changes will be overwritten on the next configuration
# switch.
${config.${namespace}.hardware.raspberry-pi.config-generated}
'';
};
firmware = pkgs.${namespace}.raspberrypifw;
};
populateUbootBuilder = import ./uboot-builder.nix {
inherit ubootBinName;
pkgs = pkgs.buildPackages;
ubootPackage = pkgs.${namespace}.uboot-pi5;
firmwareBuilder = firmwarePopulateCmd;
extlinuxConfBuilder = config.boot.loader.generic-extlinux-compatible.populateCmd;
};
firmwarePopulateCmd = "${populateFirmwareBuilder} ${firmwareBuilderArgs}";
firmwareBuilderArgs = lib.optionalString (!true) " -r";
# these will receive the top-level path as an argument when invoked as
# system.build.installBootloader
builder = {
# system.build.installBootLoader
uboot = "${ubootBuilder} -f /boot/firmware -b /boot -c";
};
# firmware: caller must provide `-c <nixos configuration>` and `-f <firmware target path>`
# boot: caller must provide `-c <nixos configuration>` and `-b <boot-dir>`
populateCmds = {
uboot = {
firmware = "${populateUbootBuilder}";
boot = "${populateUbootBuilder}";
};
};
in
{
options.${namespace}.hardware.raspberry-pi = {
@@ -38,6 +142,7 @@ in
imports = [
./audio.nix
./bluetooth.nix
./config.nix
./i2c.nix
./leds.nix
./modesetting.nix
@@ -60,7 +165,10 @@ in
"reset-raspberrypi" # required for vl805 firmware to load
]);
loader = {
generic-extlinux-compatible.enable = lib.mkDefault true;
generic-extlinux-compatible = {
enable = lib.mkDefault true;
useGenerationDeviceTree = false;
};
grub.enable = lib.mkForce false;
};
};
@@ -150,12 +258,21 @@ in
i2c.enable = lib.mkDefault true;
};
# Pi specific system tags
system.nixos.tags = [
"raspberry-pi-${cfg.variant}"
# config.boot.loader.raspberry-pi.bootloader
config.boot.kernelPackages.kernel.version
];
system = {
build.installBootLoader = lib.mkOverride 60 (builder."uboot");
boot = {
loader = {
id = lib.mkOverride 60 ("raspberrypi-uboot");
kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target;
};
};
# Pi specific system tags
nixos.tags = [
"raspberry-pi-${cfg.variant}"
# config.boot.loader.raspberry-pi.bootloader
config.boot.kernelPackages.kernel.version
];
};
# Common programs
programs.kdeconnect.enable = lib.mkDefault false;
@@ -191,11 +308,6 @@ in
};
nixpkgs.overlays = [ ] ++ (if cfg.variant == "5" then [
(final: prev: {
ubootRaspberryPi5 = prev.uboot.ubootRaspberryPi4_64Bit.override {
defconfig = "rpi_5_defconfig";
};
})
(final: prev: {
# https://github.com/nvmd/nixos-raspberrypi/issues/64
# credit for the initial version of this snippet goes to @micahcc

View File

@@ -0,0 +1,18 @@
{ pkgs
, configTxt
, firmware ? pkgs.raspberrypifw
}:
pkgs.replaceVarsWith {
src = ./firmware-builder.sh;
isExecutable = true;
replacements = {
inherit (pkgs) bash;
path = pkgs.lib.makeBinPath [
pkgs.coreutils
];
inherit firmware configTxt;
};
}

View File

@@ -0,0 +1,92 @@
#! @bash@/bin/sh -e
shopt -s nullglob
export PATH=/empty:@path@
usage() {
echo "usage: $0 -c <path-to-default-configuration> [-d <firmware-dir>] [-r]" >&2
exit 1
}
default= # Default configuration
target=/boot/firmware # Firmware target directory
while getopts "c:d:r" opt; do
case "$opt" in
c) default="$OPTARG" ;;
d) target="$OPTARG" ;;
r) useVendorDeviceTree=1 ;;
\?) usage ;;
esac
done
# Copy a file from the Nix store to $target.
declare -A filesCopied
copyForced() {
local src="$1"
local dst="$2"
cp $src $dst.tmp
mv $dst.tmp $dst
}
# Add the firmware files
# fwdir=@firmware@/share/raspberrypi/boot/
SRC_FIRMWARE_DIR=@firmware@/share/raspberrypi/boot
dtb_path=$SRC_FIRMWARE_DIR
echo "copying firmware..."
# Device Tree
if [ -n "$useVendorDeviceTree" ]; then
echo -n "using vendor firmware from "
dtb_path=$SRC_FIRMWARE_DIR
else
echo -n "using default generation's kernel device tree binaries: "
dtb_path=$(readlink -f $default/dtbs)
fi
echo $dtb_path
DTBS=("$dtb_path"/*.dtb)
for dtb in "${DTBS[@]}"; do
# for dtb in $dtb_path/broadcom/*.dtb; do
dst="$target/$(basename $dtb)"
copyForced $dtb "$dst"
filesCopied[$dst]=1
done
SRC_OVERLAYS_DIR="$dtb_path/overlays"
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
mkdir -p $target/overlays
for ovr in "${SRC_OVERLAYS[@]}"; do
# for ovr in $dtb_path/overlays/*; do
dst="$target/overlays/$(basename $ovr)"
copyForced $ovr "$dst"
filesCopied[$dst]=1
done
# remove obsolete device tree files
for fn in $target/*.dtb $target/overlays/*; do
if ! test "${filesCopied[$fn]}" = 1; then
rm -vf -- "$fn"
fi
done
# Boot code
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
for SRC in "${STARTFILES[@]}" "$BOOTCODE" "${FIXUPS[@]}"; do
dst="$target/$(basename $SRC)"
copyForced "$SRC" "$dst"
done
echo "copying config.txt..."
# Add the config.txt
copyForced @configTxt@ $target/config.txt
echo "raspberry pi firmware installed"

View File

@@ -0,0 +1,75 @@
#! @bash@/bin/sh -e
# shellcheck disable=SC3030,SC3043,SC3044,SC3054
shopt -s nullglob
export PATH=/empty:@path@
usage() {
echo "usage: $0 -c <path-to-configuration> [-d <destination-dir>] [-r]" >&2
exit 1
}
generationPath= # Path to nixos configuration/generation
target=/boot/firmware # Device tree files target directory
while getopts "c:d:r" opt; do
case "$opt" in
c) generationPath="$OPTARG" ;;
d) target="$OPTARG" ;;
r) useVendorDeviceTree=1 ;;
\?) usage ;;
esac
done
# Copy a file from the Nix store to $target.
declare -A filesCopied
copyForced() {
local src="$1"
local dst="$2"
local dstTmp="$dst.tmp.$$"
cp "$src" "$dstTmp"
mv "$dstTmp" "$dst"
}
echo "$0: $@"
echo -n "installing device tree files: "
# Device Tree
if [ -n "$useVendorDeviceTree" ]; then
echo -n "vendor firmware "
dtb_path=@firmware@/share/raspberrypi/boot
else
echo -n "generation's kernel's "
dtb_path=$(readlink -f "$generationPath/dtbs")
fi
echo "$dtb_path"
# firmware package has dtbs in its root,
# dtbs built with kernel are in broadcom/
DTBS=("$dtb_path"/*.dtb "$dtb_path"/broadcom/*.dtb)
for dtb in "${DTBS[@]}"; do
dst="$target/$(basename "$dtb")"
copyForced "$dtb" "$dst"
filesCopied[$dst]=1
done
SRC_OVERLAYS=("$dtb_path/overlays"/*)
mkdir -p "$target/overlays"
for ovr in "${SRC_OVERLAYS[@]}"; do
dst="$target/overlays/$(basename "$ovr")"
copyForced "$ovr" "$dst"
filesCopied[$dst]=1
done
# remove obsolete device tree files
for fn in $target/*.dtb $target/overlays/*; do
if ! test "${filesCopied[$fn]}" = 1; then
rm -vf -- "$fn"
fi
done

View File

@@ -0,0 +1,66 @@
#! @bash@/bin/sh -e
# shellcheck disable=SC3030,SC3043,SC3044,SC3054
shopt -s nullglob
export PATH=/empty:@path@
usage() {
echo "usage: $0 -c <path-to-configuration> [-d <firmware-dir>]" >&2
exit 1
}
generationPath= # Path to nixos configuration/generation
target=/boot/firmware # Firmware target directory
while getopts "c:d:" opt; do
case "$opt" in
c) generationPath="$OPTARG" ;;
d) target="$OPTARG" ;;
\?) usage ;;
esac
done
# Copy a file from the Nix store to $target.
declare -A filesCopied
copyForced() {
local src="$1"
local dst="$2"
local dstTmp="$dst.tmp.$$"
cp "$src" "$dstTmp"
mv "$dstTmp" "$dst"
}
# Add the firmware files
# fwdir=@firmware@/share/raspberrypi/boot/
SRC_FIRMWARE_DIR=@firmware@/share/raspberrypi/boot
echo "copying raspberry pi firmware..."
# Boot code
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
for SRC in "${STARTFILES[@]}" "$BOOTCODE" "${FIXUPS[@]}"; do
dst="$target/$(basename "$SRC")"
copyForced "$SRC" "$dst"
filesCopied[$dst]=1
done
# remove obsolete firmware files
for fn in $target/start*.elf $target/fixup*.dat; do
if ! test "${filesCopied[$fn]}" = 1; then
rm -vf -- "$fn"
fi
done
echo "copying config.txt..."
# Add the config.txt
copyForced @configTxt@ "$target/config.txt"
echo "raspberry pi firmware installed"

View File

@@ -0,0 +1,146 @@
#! @bash@/bin/sh -e
# shellcheck disable=SC3043,SC3044,SC3054
shopt -s nullglob
export PATH=/empty:@path@
# used to track copied generations to decide which are obsolete
# and need to be removed
declare -A activeGenerations
moveWBackup() {
local src="$1"
local dst="$2"
# Backup $dst if already exists
local dstBkp="$dst.bkp.$$"
if [ -e "$dst" ]; then
mv "$dst" "$dstBkp"
fi
# Move $src as "new" $dst
mv "$src" "$dst"
# Remove backup directory of the previous $dst
rm -rf "$dstBkp"
}
# Copy generation's kernel, initrd, cmdline to `gensDir/generationName`.
addEntry() {
local generationPath="$1"
local generationName="$2"
local gensDir="$3"
local dst="$gensDir/$generationName"
echo "* nixos generation '$generationName' -> $dst"
# Don't copy the files if $dst already exists, unless it's the default
# configuration.
# This means that we have to create $dst atomically to prevent partially
# copied generations if this script is ever interrupted.
#
# For "default" generation: make backup and then replace with the new
# "default", minimizing the time when where isn't any "default" generation
# directory
if ! [ -e $dst ] || [ "$generationName" = "default" ]; then
local dstTmp="$dst.tmp.$$"
mkdir -p "$dstTmp" || true
@nixosGenBuilder@ -c "$generationPath" -n "$generationName" -d "$dstTmp"
# Move new generation on its place, backing up the previous version
# if it exists
# This may only happen when "$generationName" = "default"
moveWBackup "$dstTmp" "$dst"
fi
activeGenerations["$generationName"]=1
}
removeObsoleteGenerations() {
local path="$1"
echo "removing obsolete generations in $path..."
for gen in $path/*; do
if ! [ "${activeGenerations["$(basename "$gen")"]}" = 1 ]; then
echo "* $gen is obsolete"
rm -vrf "$gen"
fi
done
}
addAllEntries() {
local defaultGenerationPath="$1"
local outdir="$2"
local numGenerations="$3"
local gensDir="$outdir/@nixosGenerationsDir@"
mkdir -p "$gensDir" || true
# Add default generation
addEntry "$defaultGenerationPath" default "$gensDir"
if [ "$numGenerations" -gt 0 ]; then
# Add up to $numGenerations generations of the system profile, in reverse
# (most recent to least recent) order.
for generation in $(
(cd /nix/var/nix/profiles && ls -d system-*-link) \
| sed 's/system-\([0-9]\+\)-link/\1/' \
| sort -n -r \
| head -n "$numGenerations"); do
link=/nix/var/nix/profiles/system-$generation-link
addEntry "$link" "${generation}-default" "$gensDir"
for specialisation in $(
ls /nix/var/nix/profiles/system-$generation-link/specialisation \
| sort -n -r); do
link=/nix/var/nix/profiles/system-$generation-link/specialisation/$specialisation
addEntry "$link" "${generation}-${specialisation}" "$gensDir"
done
done
fi
removeObsoleteGenerations "$gensDir"
}
usage() {
echo "usage: $0 -c <path-to-default-configuration> [-b <boot-dir>] [-g <num-generations>]" >&2
exit 1
}
default= # Default configuration
numGenerations=0 # Number of other generations to keep (kernel, initrd, DTBs, overlays)
echo "$0: $@"
while getopts "c:b:g:f:" opt; do
case "$opt" in
c) default="$OPTARG" ;;
b) boottarget="$OPTARG" ;;
g) numGenerations="$OPTARG" ;;
f) fwtarget="$OPTARG" ;;
\?) usage ;;
esac
done
if [ -z "$boottarget" ] && [ -z "$fwtarget" ]; then
echo "Error: at least one of \`-b <boot-dir>\` and \`-f <firmware-dir>\` must be set"
usage
fi
if [ -n "$fwtarget" ]; then
echo "installing nixos-generation-independent firmware..."
@installFirmwareBuilder@ -c "$default" -d "$fwtarget"
echo "installing nixos generations..."
addAllEntries "$default" "$fwtarget" "$numGenerations"
fi
if [ -n "$boottarget" ]; then
echo "'-b $boottarget' isn't used when loading the kernel directly with \`kernel\`: "\
"kernels are copied directly to <firmware-dir>"
exit 0
fi
echo "generational bootloader installed"

View File

@@ -0,0 +1,23 @@
{ pkgs
, ubootPackage
, ubootBinName ? "u-boot.bin"
, extlinuxConfBuilder
, firmwareBuilder
}:
pkgs.replaceVarsWith {
src = ./uboot-builder.sh;
isExecutable = true;
replacements = {
inherit (pkgs) bash;
path = pkgs.lib.makeBinPath [
pkgs.coreutils
];
uboot = ubootPackage;
inherit ubootBinName;
inherit extlinuxConfBuilder;
inherit firmwareBuilder;
};
}

View File

@@ -0,0 +1,67 @@
#! @bash@/bin/sh -e
shopt -s nullglob
export PATH=/empty:@path@
usage() {
echo "usage: $0 -f <firmware-dir> -b <boot-dir> -c <path-to-default-configuration>" >&2
exit 1
}
default= # Default configuration, needed for extlinux
# fwtarget=/boot/firmware # firmware target directory
# boottarget=/boot # boot configuration target directory
echo "uboot-builder: $@"
while getopts "c:b:f:" opt; do
case "$opt" in
c) default="$OPTARG" ;;
b) boottarget="$OPTARG" ;;
f) fwtarget="$OPTARG" ;;
\?) usage ;;
esac
done
if [ -z "$boottarget" ] && [ -z "$fwtarget" ]; then
echo "Error: at least one of \`-b <boot-dir>\` and \`-f <firmware-dir>\` must be set"
usage
fi
# # process arguments for this builder, then pass the remainder to extlinux'
# while getopts ":f:" opt; do
# case "$opt" in
# f) target="$OPTARG" ;;
# *) ;;
# esac
# done
# shift $((OPTIND-2))
# extlinuxBuilderExtraArgs="$@"
copyForced() {
local src="$1"
local dst="$2"
cp $src $dst.tmp
mv $dst.tmp $dst
}
if [ -n "$fwtarget" ]; then
@firmwareBuilder@ -c $default -d $fwtarget
echo "copying u-boot binary..."
copyForced @uboot@/u-boot.bin $fwtarget/@ubootBinName@
fi
if [ -n "$boottarget" ]; then
echo "generating extlinux configuration..."
@extlinuxConfBuilder@ -c $default -d $boottarget
fi
msg=""
if [ -n "$fwtarget" ]; then
msg="uboot"
fi
if [ -n "$boottarget" ]; then
msg="$msg+extlinux"
fi
echo "$msg bootloader installed"

View File

@@ -31,7 +31,7 @@ let
};
llama-cpp = {
enable = true;
enable = false;
port = 8127;
host = "0.0.0.0";
openFirewall = cfg.openFirewall;

View File

@@ -25,21 +25,26 @@ let
name = "steam";
prep-cmd = [
{
do = "${pkgs.cosmic-randr}/bin/cosmic-randr mode HDMI-A-1 1280 800";
undo = "${pkgs.cosmic-randr}/bin/cosmic-randr mode HDMI-A-1 1920 1080";
}
{
do = "${pkgs.util-linux}/bin/setsid ${pkgs.steam}/bin/steam steam://open/bigpicture";
undo = "${pkgs.util-linux}/bin/setsid ${pkgs.steam}/bin/steam steam://close/bigpicture";
}
];
detached = [
"${pkgs.util-linux}/bin/setsid ${pkgs.steam}/bin/steam steam://open/bigpicture"
];
# detached = [
# "${pkgs.steam}/bin/steam steam://open/bigpicture"
# ];
exclude-global-prep-cmd = "false";
auto-detach = "true";
}
{
name = "1440p Desktop";
name = "800p Desktop";
prep-cmd = [
{
do = "''${pkgs.kdePackages.libkscreen}/bin/kscreen-doctor output.DP-4.mode.2560x1440@60";
undo = "''${pkgs.kdePackages.libkscreen}/bin/kscreen-doctor output.DP-4.mode.3440x1440@60";
do = "${pkgs.cosmic-randr}/bin/cosmic-randr mode HDMI-A-1 1280 800";
undo = "${pkgs.cosmic-randr}/bin/cosmic-randr mode HDMI-A-1 1920 1080";
}
];
exclude-global-prep-cmd = "false";

View File

@@ -7,6 +7,7 @@ let
nixpkgs = inputs.nixpkgs;
inherit self;
};
ubootPackages = final.callPackage ../../packages/uboot { };
in
{
${namespace} = prev.${namespace} // {
@@ -33,5 +34,7 @@ in
# RC
linuxPackages_cachyos-rc-lto = cachyosPackages.cachyos-rc-lto;
linuxPackages_cachyos-rc-lto-znver4 = cachyosPackages.cachyos-rc-lto-znver4;
uboot-pi5 = ubootPackages.ubootRaspberryPi5;
};
}

View File

@@ -268,7 +268,7 @@ in
};
ubootRaspberryPi5 = buildUBoot {
defconfig = "rpi_5_defconfig";
defconfig = "rpi_arm64_defconfig";
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "u-boot.bin" ];
};

View File

@@ -12,46 +12,46 @@ in
supportedFilesystems = lib.mkForce [ ];
};
# hardware.raspberry-pi.config = {
# all = {
# # [all] conditional filter, https://www.raspberrypi.com/documentation/computers/config_txt.html#conditional-filters
${namespace}.hardware.raspberry-pi.config = {
all = {
# [all] conditional filter, https://www.raspberrypi.com/documentation/computers/config_txt.html#conditional-filters
# options = {
# # https://www.raspberrypi.com/documentation/computers/config_txt.html#enable_uart
# # in conjunction with `console=serial0,115200` in kernel command line (`cmdline.txt`)
# # creates a serial console, accessible using GPIOs 14 and 15 (pins
# # 8 and 10 on the 40-pin header)
# enable_uart = {
# enable = true;
# value = true;
# };
# # https://www.raspberrypi.com/documentation/computers/config_txt.html#uart_2ndstage
# # enable debug logging to the UART, also automatically enables
# # UART logging in `start.elf`
# uart_2ndstage = {
# enable = true;
# value = true;
# };
# };
options = {
# https://www.raspberrypi.com/documentation/computers/config_txt.html#enable_uart
# in conjunction with `console=serial0,115200` in kernel command line (`cmdline.txt`)
# creates a serial console, accessible using GPIOs 14 and 15 (pins
# 8 and 10 on the 40-pin header)
enable_uart = {
enable = true;
value = true;
};
# https://www.raspberrypi.com/documentation/computers/config_txt.html#uart_2ndstage
# enable debug logging to the UART, also automatically enables
# UART logging in `start.elf`
uart_2ndstage = {
enable = true;
value = true;
};
};
# # Base DTB parameters
# # https://github.com/raspberrypi/linux/blob/a1d3defcca200077e1e382fe049ca613d16efd2b/arch/arm/boot/dts/overlays/README#L132
# base-dt-params = {
# Base DTB parameters
# https://github.com/raspberrypi/linux/blob/a1d3defcca200077e1e382fe049ca613d16efd2b/arch/arm/boot/dts/overlays/README#L132
base-dt-params = {
# # https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#enable-pcie
# pciex1 = {
# enable = true;
# value = "on";
# };
# # PCIe Gen 3.0
# # https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#pcie-gen-3-0
# pciex1_gen = {
# enable = true;
# value = "3";
# };
# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#enable-pcie
pciex1 = {
enable = true;
value = "on";
};
# PCIe Gen 3.0
# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#pcie-gen-3-0
pciex1_gen = {
enable = true;
value = "3";
};
# };
};
# };
# };
};
};
}