mirror of
https://github.com/nix-community/raspberry-pi-nix.git
synced 2025-11-08 19:46:03 +01:00
Merge fb248c0047 into f317116725
This commit is contained in:
commit
c0cba6304f
17 changed files with 570 additions and 229 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
result
|
||||||
66
README.md
66
README.md
|
|
@ -13,7 +13,7 @@ this repository aims to deliver the following benefits:
|
||||||
3. Make it easy to build an image suitable for flashing to an sd-card,
|
3. Make it easy to build an image suitable for flashing to an sd-card,
|
||||||
without the need to first go through an installation media.
|
without the need to first go through an installation media.
|
||||||
|
|
||||||
The important modules are `overlay/default.nix`, `rpi/default.nix`,
|
The important modules are `overlays/default.nix`, `rpi/default.nix`,
|
||||||
and `rpi/config.nix`. The other modules are mostly wrappers that set
|
and `rpi/config.nix`. The other modules are mostly wrappers that set
|
||||||
`config.txt` settings and enable required kernel modules.
|
`config.txt` settings and enable required kernel modules.
|
||||||
|
|
||||||
|
|
@ -25,7 +25,11 @@ upgrading.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
See the `rpi-example` config in this flake for an example config built by CI.
|
See the `/example` in this flake for an configs [built by CI](https://buildbot.nix-community.org/#/projects/15).
|
||||||
|
|
||||||
|
* `/example/direct.nix` boots directly into the linux kernel
|
||||||
|
* `/example/uboot.nix` boots into uboot, provides a generation selection menu,
|
||||||
|
then into linux
|
||||||
|
|
||||||
## Using the provided cache to avoid compiling linux
|
## Using the provided cache to avoid compiling linux
|
||||||
This repo uses the raspberry pi linux kernel fork, and compiling linux takes a
|
This repo uses the raspberry pi linux kernel fork, and compiling linux takes a
|
||||||
|
|
@ -36,35 +40,53 @@ to use this cache.
|
||||||
|
|
||||||
## Building an sd-card image
|
## Building an sd-card image
|
||||||
|
|
||||||
Include the provided `sd-image` nixos module this flake provides, then an image
|
Use [`make-disk-image.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/make-disk-image.nix) like so:
|
||||||
suitable for flashing to an sd-card can be found at the attribute
|
|
||||||
`config.system.build.sdImage`. For example, if you wanted to build an image for
|
|
||||||
`rpi-example` in the above configuration example you could run:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage'
|
system.build.image = (import "${toString modulesPath}/../lib/make-disk-image.nix" {
|
||||||
|
inherit lib config pkgs;
|
||||||
|
format = "raw";
|
||||||
|
partitionTableType = "efi";
|
||||||
|
copyChannel = false;
|
||||||
|
diskSize = "auto";
|
||||||
|
additionalSpace = "64M";
|
||||||
|
bootSize = "128M";
|
||||||
|
touchEFIVars = false;
|
||||||
|
installBootLoader = true;
|
||||||
|
label = "nixos";
|
||||||
|
deterministic = true;
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## The firmware partition
|
Add the configuration for your specific board:
|
||||||
|
|
||||||
The image produced by this package is partitioned in the same way as the aarch64
|
```
|
||||||
installation media from nixpkgs: There is a firmware partition that contains
|
raspberry-pi-nix.board = "bcm2711";
|
||||||
necessary firmware, the kernel or u-boot, and config.txt. Then there is another
|
hardware.raspberry-pi.config = {
|
||||||
partition (labeled `NIXOS_SD`) that contains everything else. The firmware and
|
...
|
||||||
`config.txt` file are managed by NixOS modules defined in this
|
};
|
||||||
package. Additionally, a systemd service will update the firmware and
|
```
|
||||||
`config.txt` in the firmware partition __in place__. If uboot is enabled then
|
|
||||||
linux kernels are stored in the `NIXOS_SD` partition and will be booted by
|
Then get nix to build your image:
|
||||||
u-boot in the firmware partition.
|
|
||||||
|
```
|
||||||
|
nix build '.#nixosConfigurations.my-raspberry-pi.config.system.build.image'
|
||||||
|
```
|
||||||
|
|
||||||
|
## The partition layout
|
||||||
|
|
||||||
|
The image produced is partitioned in the same way as any x86 EFI-boot disk generated by `make-disk-image.nix`: There is a partition labelled `ESP` which contains the firmware, kernel, config.txt and u-boot or cmdline.txt. The second partition labeled `nixos` is the root partition which contains the nix store and everything else.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The boot partition is called ESP which stands for EFI System Partition. Raspberry Pis don't boot with EFI, but `ESP` is the hardcoded partition name used in `make-disk-image.nix` when using `partitionTableType=efi`, which just happens to be the closest partition layout to what's needed. By setting `touchEFIVars=false` you can avoid any EFI boot variables being set, not that they will affect the Raspberry Pi's boot process.
|
||||||
|
|
||||||
|
Files in the boot partition are managed as long as the `rpi` package is imported, whether using uboot or direct-to-kernel boot. Following the upstream behaviour of `generic-extlinux-compatible/default.nix`, these files are not overwritten once created. The only exceptions are `cmdline.txt` and `config.txt` which will get overwritten every time `nixos-rebuild switch` is run. In practice, this means that you can enjoy kernel updates (because each version is put into a new file), but firmware / bootcode updates will probably not be installed if they arrive in an existing file.
|
||||||
|
|
||||||
## `config.txt` generation
|
## `config.txt` generation
|
||||||
|
|
||||||
As noted, the `config.txt` file is generated by the NixOS
|
The `config.txt` file is generated by `rpi` package and automatically written to the boot partition when running `nixos-rebuild switch`.
|
||||||
configuration and automatically updated on when the nix configuration
|
|
||||||
is modified.
|
|
||||||
|
|
||||||
The relevant nixos option is
|
The relevant nixos option is `hardware.raspberry-pi.config`. Configuration is partitioned into
|
||||||
`hardware.raspberry-pi.config`. Configuration is partitioned into
|
|
||||||
three sections:
|
three sections:
|
||||||
|
|
||||||
1. Base device tree parameters `base-dt-params`
|
1. Base device tree parameters `base-dt-params`
|
||||||
|
|
|
||||||
8
atomic-copy/atomic-copy-clobber.nix
Normal file
8
atomic-copy/atomic-copy-clobber.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
pkgs.substituteAll {
|
||||||
|
src = ./atomic-copy-clobber.sh;
|
||||||
|
isExecutable = true;
|
||||||
|
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
|
||||||
|
inherit (pkgs) bash;
|
||||||
|
}
|
||||||
18
atomic-copy/atomic-copy-clobber.sh
Normal file
18
atomic-copy/atomic-copy-clobber.sh
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#! @bash@/bin/sh -e
|
||||||
|
|
||||||
|
# copy+paste of copyToKernelsDir https://github.com/NixOS/nixpkgs/blob/904ecf0b4e055dc465f5ae6574be2af8cc25dec3/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh#L53
|
||||||
|
# but without the check which skips the copy if the destination exists
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
export PATH=/empty
|
||||||
|
for i in @path@; do PATH=$PATH:$i/bin; done
|
||||||
|
|
||||||
|
src=$(readlink -f "$1")
|
||||||
|
dst="$2"
|
||||||
|
|
||||||
|
# Create $dst atomically to prevent partially copied files
|
||||||
|
# if this script is ever interrupted.
|
||||||
|
dstTmp=$dst.tmp.$$
|
||||||
|
cp -r $src $dstTmp
|
||||||
|
mv $dstTmp $dst
|
||||||
8
atomic-copy/atomic-copy-safe.nix
Normal file
8
atomic-copy/atomic-copy-safe.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
pkgs.substituteAll {
|
||||||
|
src = ./atomic-copy-safe.sh;
|
||||||
|
isExecutable = true;
|
||||||
|
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
|
||||||
|
inherit (pkgs) bash;
|
||||||
|
}
|
||||||
20
atomic-copy/atomic-copy-safe.sh
Normal file
20
atomic-copy/atomic-copy-safe.sh
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#! @bash@/bin/sh -e
|
||||||
|
|
||||||
|
# copy+paste of copyToKernelsDir https://github.com/NixOS/nixpkgs/blob/904ecf0b4e055dc465f5ae6574be2af8cc25dec3/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh#L53
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
export PATH=/empty
|
||||||
|
for i in @path@; do PATH=$PATH:$i/bin; done
|
||||||
|
|
||||||
|
src=$(readlink -f "$1")
|
||||||
|
dst="$2"
|
||||||
|
|
||||||
|
# Don't copy the file if $dst already exists.
|
||||||
|
# Also create $dst atomically to prevent partially copied files
|
||||||
|
# if this script is ever interrupted.
|
||||||
|
if ! test -e $dst; then
|
||||||
|
dstTmp=$dst.tmp.$$
|
||||||
|
cp -r $src $dstTmp
|
||||||
|
mv $dstTmp $dst
|
||||||
|
fi
|
||||||
81
example/common.nix
Normal file
81
example/common.nix
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
{ config, inputs, lib, modulesPath, pkgs, ... }: {
|
||||||
|
time.timeZone = "America/New_York";
|
||||||
|
users.users.root.initialPassword = "root";
|
||||||
|
networking = {
|
||||||
|
hostName = "example";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces = {
|
||||||
|
wlan0.useDHCP = true;
|
||||||
|
eth0.useDHCP = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
raspberry-pi-nix = {
|
||||||
|
board = "bcm2711";
|
||||||
|
};
|
||||||
|
hardware = {
|
||||||
|
raspberry-pi = {
|
||||||
|
config = {
|
||||||
|
all = {
|
||||||
|
base-dt-params = {
|
||||||
|
BOOT_UART = {
|
||||||
|
value = 1;
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
uart_2ndstage = {
|
||||||
|
value = 1;
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
dt-overlays = {
|
||||||
|
disable-bt = {
|
||||||
|
enable = true;
|
||||||
|
params = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
security.rtkit.enable = true;
|
||||||
|
services.pipewire = {
|
||||||
|
enable = true;
|
||||||
|
alsa.enable = true;
|
||||||
|
alsa.support32Bit = true;
|
||||||
|
pulse.enable = true;
|
||||||
|
};
|
||||||
|
fileSystems = {
|
||||||
|
"/boot" = {
|
||||||
|
device = "/dev/disk/by-label/ESP";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
"/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
autoResize = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
boot.growPartition = true;
|
||||||
|
system.build.image = (import "${toString modulesPath}/../lib/make-disk-image.nix" {
|
||||||
|
inherit lib config pkgs;
|
||||||
|
format = "raw";
|
||||||
|
partitionTableType = "efi";
|
||||||
|
copyChannel = false;
|
||||||
|
diskSize = "auto";
|
||||||
|
additionalSpace = "64M";
|
||||||
|
bootSize = "128M";
|
||||||
|
touchEFIVars = false;
|
||||||
|
installBootLoader = true;
|
||||||
|
label = "nixos";
|
||||||
|
deterministic = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
nix.settings.substituters = lib.mkForce config.nix.settings.trusted-substituters;
|
||||||
|
nix.settings.trusted-substituters = [
|
||||||
|
"https://cache.nixos.org/"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
];
|
||||||
|
nix.settings.trusted-public-keys = [
|
||||||
|
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
{ pkgs, lib, ... }: {
|
|
||||||
time.timeZone = "America/New_York";
|
|
||||||
users.users.root.initialPassword = "root";
|
|
||||||
networking = {
|
|
||||||
hostName = "example";
|
|
||||||
useDHCP = false;
|
|
||||||
interfaces = {
|
|
||||||
wlan0.useDHCP = true;
|
|
||||||
eth0.useDHCP = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
raspberry-pi-nix.board = "bcm2711";
|
|
||||||
hardware = {
|
|
||||||
raspberry-pi = {
|
|
||||||
config = {
|
|
||||||
all = {
|
|
||||||
base-dt-params = {
|
|
||||||
BOOT_UART = {
|
|
||||||
value = 1;
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
uart_2ndstage = {
|
|
||||||
value = 1;
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
dt-overlays = {
|
|
||||||
disable-bt = {
|
|
||||||
enable = true;
|
|
||||||
params = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
security.rtkit.enable = true;
|
|
||||||
services.pipewire = {
|
|
||||||
enable = true;
|
|
||||||
alsa.enable = true;
|
|
||||||
alsa.support32Bit = true;
|
|
||||||
pulse.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
6
example/direct.nix
Normal file
6
example/direct.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{ config, inputs, lib, modulesPath, pkgs, ... }: {
|
||||||
|
imports = [
|
||||||
|
./common.nix
|
||||||
|
];
|
||||||
|
raspberry-pi-nix.uboot.enable = false;
|
||||||
|
}
|
||||||
6
example/uboot.nix
Normal file
6
example/uboot.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{ config, inputs, lib, modulesPath, pkgs, ... }: {
|
||||||
|
imports = [
|
||||||
|
./common.nix
|
||||||
|
];
|
||||||
|
raspberry-pi-nix.uboot.enable = true;
|
||||||
|
}
|
||||||
13
flake.nix
13
flake.nix
|
|
@ -63,12 +63,16 @@
|
||||||
core-overlay = self.overlays.core;
|
core-overlay = self.overlays.core;
|
||||||
libcamera-overlay = self.overlays.libcamera;
|
libcamera-overlay = self.overlays.libcamera;
|
||||||
};
|
};
|
||||||
sd-image = import ./sd-image;
|
generic-extlinux-compatible = import ./generic-extlinux-compatible;
|
||||||
};
|
};
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
rpi-example = srcs.nixpkgs.lib.nixosSystem {
|
rpi-example-direct = srcs.nixpkgs.lib.nixosSystem {
|
||||||
system = "aarch64-linux";
|
system = "aarch64-linux";
|
||||||
modules = [ self.nixosModules.raspberry-pi self.nixosModules.sd-image ./example ];
|
modules = [ self.nixosModules.raspberry-pi ./example/direct.nix ];
|
||||||
|
};
|
||||||
|
rpi-example-uboot = srcs.nixpkgs.lib.nixosSystem {
|
||||||
|
system = "aarch64-linux";
|
||||||
|
modules = [ self.nixosModules.raspberry-pi ./example/uboot.nix ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
checks.aarch64-linux = self.packages.aarch64-linux;
|
checks.aarch64-linux = self.packages.aarch64-linux;
|
||||||
|
|
@ -85,7 +89,8 @@
|
||||||
board-attr-set;
|
board-attr-set;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
example-sd-image = self.nixosConfigurations.rpi-example.config.system.build.sdImage;
|
example-image-direct = self.nixosConfigurations.rpi-example-direct.config.system.build.image;
|
||||||
|
example-image-uboot = self.nixosConfigurations.rpi-example-uboot.config.system.build.image;
|
||||||
firmware = pinned.raspberrypifw;
|
firmware = pinned.raspberrypifw;
|
||||||
libcamera = pinned.libcamera;
|
libcamera = pinned.libcamera;
|
||||||
wireless-firmware = pinned.raspberrypiWirelessFirmware;
|
wireless-firmware = pinned.raspberrypiWirelessFirmware;
|
||||||
|
|
|
||||||
5
generic-extlinux-compatible/README.md
Normal file
5
generic-extlinux-compatible/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Copied from:
|
||||||
|
|
||||||
|
https://github.com/NixOS/nixpkgs/blob/93fb96ecdead26092b8425383fffb0422bf52182/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
|
||||||
|
|
||||||
|
The goal is to merge the changes back in once tested.
|
||||||
3
generic-extlinux-compatible/default.nix
Normal file
3
generic-extlinux-compatible/default.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{ ... }: {
|
||||||
|
imports = [ ./generic-extlinux-compatible.nix ];
|
||||||
|
}
|
||||||
8
generic-extlinux-compatible/extlinux-conf-builder.nix
Normal file
8
generic-extlinux-compatible/extlinux-conf-builder.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
pkgs.substituteAll {
|
||||||
|
src = ./extlinux-conf-builder.sh;
|
||||||
|
isExecutable = true;
|
||||||
|
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
|
||||||
|
inherit (pkgs) bash;
|
||||||
|
}
|
||||||
163
generic-extlinux-compatible/extlinux-conf-builder.sh
Normal file
163
generic-extlinux-compatible/extlinux-conf-builder.sh
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
#! @bash@/bin/sh -e
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
export PATH=/empty
|
||||||
|
for i in @path@; do PATH=$PATH:$i/bin; done
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>] [-n <dtbName>] [-r]" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout= # Timeout in centiseconds
|
||||||
|
default= # Default configuration
|
||||||
|
target=/boot # Target directory
|
||||||
|
numGenerations=0 # Number of other generations to include in the menu
|
||||||
|
|
||||||
|
while getopts "t:c:d:g:n:r" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
t) # U-Boot interprets '0' as infinite and negative as instant boot
|
||||||
|
if [ "$OPTARG" -lt 0 ]; then
|
||||||
|
timeout=0
|
||||||
|
elif [ "$OPTARG" = 0 ]; then
|
||||||
|
timeout=-10
|
||||||
|
else
|
||||||
|
timeout=$((OPTARG * 10))
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
c) default="$OPTARG" ;;
|
||||||
|
d) target="$OPTARG" ;;
|
||||||
|
g) numGenerations="$OPTARG" ;;
|
||||||
|
n) dtbName="$OPTARG" ;;
|
||||||
|
r) noDeviceTree=1 ;;
|
||||||
|
\?) usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[ "$timeout" = "" -o "$default" = "" ] && usage
|
||||||
|
|
||||||
|
mkdir -p $target/nixos
|
||||||
|
mkdir -p $target/extlinux
|
||||||
|
|
||||||
|
# Convert a path to a file in the Nix store such as
|
||||||
|
# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
|
||||||
|
cleanName() {
|
||||||
|
local path="$1"
|
||||||
|
echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy a file from the Nix store to $target/nixos.
|
||||||
|
declare -A filesCopied
|
||||||
|
|
||||||
|
copyToKernelsDir() {
|
||||||
|
local src=$(readlink -f "$1")
|
||||||
|
local dst="$target/nixos/$(cleanName $src)"
|
||||||
|
# Don't copy the file if $dst already exists. This means that we
|
||||||
|
# have to create $dst atomically to prevent partially copied
|
||||||
|
# kernels or initrd if this script is ever interrupted.
|
||||||
|
if ! test -e $dst; then
|
||||||
|
local dstTmp=$dst.tmp.$$
|
||||||
|
cp -r $src $dstTmp
|
||||||
|
mv $dstTmp $dst
|
||||||
|
fi
|
||||||
|
filesCopied[$dst]=1
|
||||||
|
result=$dst
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy its kernel, initrd and dtbs to $target/nixos, and echo out an
|
||||||
|
# extlinux menu entry
|
||||||
|
addEntry() {
|
||||||
|
local path=$(readlink -f "$1")
|
||||||
|
local tag="$2" # Generation number or 'default'
|
||||||
|
|
||||||
|
if ! test -e $path/kernel -a -e $path/initrd; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
copyToKernelsDir "$path/kernel"; kernel=$result
|
||||||
|
copyToKernelsDir "$path/initrd"; initrd=$result
|
||||||
|
dtbDir=$(readlink -m "$path/dtbs")
|
||||||
|
if [ -e "$dtbDir" ]; then
|
||||||
|
copyToKernelsDir "$dtbDir"; dtbs=$result
|
||||||
|
fi
|
||||||
|
|
||||||
|
timestampEpoch=$(stat -L -c '%Z' $path)
|
||||||
|
|
||||||
|
timestamp=$(date "+%Y-%m-%d %H:%M" -d @$timestampEpoch)
|
||||||
|
nixosLabel="$(cat $path/nixos-version)"
|
||||||
|
extraParams="$(cat $path/kernel-params)"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "LABEL nixos-$tag"
|
||||||
|
if [ "$tag" = "default" ]; then
|
||||||
|
echo " MENU LABEL NixOS - Default"
|
||||||
|
else
|
||||||
|
echo " MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosLabel)"
|
||||||
|
fi
|
||||||
|
echo " LINUX ../nixos/$(basename $kernel)"
|
||||||
|
echo " INITRD ../nixos/$(basename $initrd)"
|
||||||
|
echo " APPEND init=$path/init $extraParams"
|
||||||
|
|
||||||
|
if [ -n "$noDeviceTree" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$dtbDir" ]; then
|
||||||
|
# if a dtbName was specified explicitly, use that, else use FDTDIR
|
||||||
|
if [ -n "$dtbName" ]; then
|
||||||
|
echo " FDT ../nixos/$(basename $dtbs)/${dtbName}"
|
||||||
|
else
|
||||||
|
echo " FDTDIR ../nixos/$(basename $dtbs)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -n "$dtbName" ]; then
|
||||||
|
echo "Explicitly requested dtbName $dtbName, but there's no FDTDIR - bailing out." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile="$target/extlinux/extlinux.conf.tmp.$$"
|
||||||
|
|
||||||
|
cat > $tmpFile <<EOF
|
||||||
|
# Generated file, all changes will be lost on nixos-rebuild!
|
||||||
|
|
||||||
|
# Change this to e.g. nixos-42 to temporarily boot to an older configuration.
|
||||||
|
DEFAULT nixos-default
|
||||||
|
|
||||||
|
MENU TITLE ------------------------------------------------------------
|
||||||
|
TIMEOUT $timeout
|
||||||
|
EOF
|
||||||
|
|
||||||
|
addEntry $default default >> $tmpFile
|
||||||
|
|
||||||
|
if [ "$numGenerations" -gt 0 ]; then
|
||||||
|
# Add up to $numGenerations generations of the system profile to the menu,
|
||||||
|
# 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"
|
||||||
|
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}"
|
||||||
|
done
|
||||||
|
done >> $tmpFile
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv -f $tmpFile $target/extlinux/extlinux.conf
|
||||||
|
|
||||||
|
# Remove obsolete files from $target/nixos.
|
||||||
|
for fn in $target/nixos/*; do
|
||||||
|
if ! test "${filesCopied[$fn]}" = 1; then
|
||||||
|
echo "Removing no longer needed boot file: $fn"
|
||||||
|
chmod +w -- "$fn"
|
||||||
|
rm -rf -- "$fn"
|
||||||
|
fi
|
||||||
|
done
|
||||||
132
generic-extlinux-compatible/generic-extlinux-compatible.nix
Normal file
132
generic-extlinux-compatible/generic-extlinux-compatible.nix
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
blCfg = config.boot.loader;
|
||||||
|
dtCfg = config.hardware.deviceTree;
|
||||||
|
cfg = blCfg.generic-extlinux-compatible-pi-loader;
|
||||||
|
|
||||||
|
timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
|
||||||
|
|
||||||
|
# The builder used to write during system activation
|
||||||
|
builder = import ./extlinux-conf-builder.nix { inherit pkgs; };
|
||||||
|
# The builder exposed in populateCmd, which runs on the build architecture
|
||||||
|
populateBuilder = import ./extlinux-conf-builder.nix { pkgs = pkgs.buildPackages; };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
boot.loader.generic-extlinux-compatible-pi-loader = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to generate an extlinux-compatible configuration file
|
||||||
|
under `/boot/extlinux.conf`. For instance,
|
||||||
|
U-Boot's generic distro boot support uses this file format.
|
||||||
|
|
||||||
|
See [U-boot's documentation](https://u-boot.readthedocs.io/en/latest/develop/distro.html)
|
||||||
|
for more information.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
useGenerationDeviceTree = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to generate Device Tree-related directives in the
|
||||||
|
extlinux configuration.
|
||||||
|
|
||||||
|
When enabled, the bootloader will attempt to load the device
|
||||||
|
tree binaries from the generation's kernel.
|
||||||
|
|
||||||
|
Note that this affects all generations, regardless of the
|
||||||
|
setting value used in their configurations.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
configurationLimit = mkOption {
|
||||||
|
default = 20;
|
||||||
|
example = 10;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Maximum number of configurations in the boot menu.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mirroredBoots = mkOption {
|
||||||
|
default = [ { path = "/boot"; } ];
|
||||||
|
example = [
|
||||||
|
{ path = "/boot1"; }
|
||||||
|
{ path = "/boot2"; }
|
||||||
|
];
|
||||||
|
description = ''
|
||||||
|
Mirror the boot configuration to multiple paths.
|
||||||
|
'';
|
||||||
|
|
||||||
|
type = with types; listOf (submodule {
|
||||||
|
options = {
|
||||||
|
path = mkOption {
|
||||||
|
example = "/boot1";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
The path to the boot directory where the extlinux-compatible
|
||||||
|
configuration files will be written.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
populateCmd = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
Contains the builder command used to populate an image,
|
||||||
|
honoring all options except the `-c <path-to-default-configuration>`
|
||||||
|
argument.
|
||||||
|
Useful to have for sdImage.populateRootCommands
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraCommandsAfter = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = ''
|
||||||
|
Optional commands to run after installing the bootloader.
|
||||||
|
Useful for putting Raspberry Pi firmwares on the boot partition.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = let
|
||||||
|
builderArgs = "-g ${toString cfg.configurationLimit} -t ${timeoutStr}"
|
||||||
|
+ lib.optionalString (dtCfg.name != null) " -n ${dtCfg.name}"
|
||||||
|
+ lib.optionalString (!cfg.useGenerationDeviceTree) " -r";
|
||||||
|
installBootLoader = pkgs.writeScript "install-extlinux-conf.sh" (''
|
||||||
|
#!${pkgs.runtimeShell}
|
||||||
|
set -e
|
||||||
|
'' + flip concatMapStrings cfg.mirroredBoots (args: ''
|
||||||
|
${builder} ${builderArgs} -d '${args.path}' -c "$@"
|
||||||
|
'') + ''
|
||||||
|
${lib.concatLines cfg.extraCommandsAfter}
|
||||||
|
'');
|
||||||
|
in
|
||||||
|
mkIf cfg.enable {
|
||||||
|
system.build.installBootLoader = installBootLoader;
|
||||||
|
system.boot.loader.id = "generic-extlinux-compatible-pi-loader";
|
||||||
|
|
||||||
|
boot.loader.generic-extlinux-compatible-pi-loader.populateCmd = "${populateBuilder} ${builderArgs}";
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.mirroredBoots != [ ];
|
||||||
|
message = ''
|
||||||
|
You must not remove all elements from option 'boot.loader.generic-extlinux-compatible-pi-loader.mirroredBoots',
|
||||||
|
otherwise the system will not be bootable.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
217
rpi/default.nix
217
rpi/default.nix
|
|
@ -1,15 +1,20 @@
|
||||||
{ pinned, core-overlay, libcamera-overlay }:
|
{ pinned, core-overlay, libcamera-overlay }:
|
||||||
{ lib, pkgs, config, ... }:
|
{ lib, pkgs, config, ... }:
|
||||||
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.raspberry-pi-nix;
|
cfg = config.raspberry-pi-nix;
|
||||||
version = cfg.kernel-version;
|
version = cfg.kernel-version;
|
||||||
board = cfg.board;
|
board = cfg.board;
|
||||||
kernel = config.system.build.kernel;
|
atomicCopySafe = import ../atomic-copy/atomic-copy-safe.nix { inherit pkgs; };
|
||||||
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
|
atomicCopyClobber = import ../atomic-copy/atomic-copy-clobber.nix { inherit pkgs; };
|
||||||
|
|
||||||
|
# used for direct-to-kernel boot only: emulate cleanName()
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/904ecf0b4e055dc465f5ae6574be2af8cc25dec3/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh#L47
|
||||||
|
kernelStorePath = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
|
||||||
|
kernelBootPath = "nixos/${builtins.replaceStrings [ "/nix/store/" "/" ] [ "" "-" ] kernelStorePath}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./config.nix ./i2c.nix ];
|
imports = [ ../generic-extlinux-compatible ./config.nix ./i2c.nix ];
|
||||||
|
|
||||||
options = with lib; {
|
options = with lib; {
|
||||||
raspberry-pi-nix = {
|
raspberry-pi-nix = {
|
||||||
|
|
@ -77,153 +82,16 @@ in
|
||||||
|
|
||||||
package = mkPackageOption pkgs "uboot-rpi-arm64" { };
|
package = mkPackageOption pkgs "uboot-rpi-arm64" { };
|
||||||
};
|
};
|
||||||
|
rootGPUID = mkOption {
|
||||||
|
description = "The UID of the root partition";
|
||||||
|
type = types.str;
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/23e89b7da85c3640bbc2173fe04f4bd114342367/nixos/lib/make-disk-image.nix#L177
|
||||||
|
default = "F222513B-DED1-49FA-B591-20CE86A2FE7F";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
systemd.services = {
|
|
||||||
"raspberry-pi-firmware-migrate" =
|
|
||||||
{
|
|
||||||
description = "update the firmware partition";
|
|
||||||
wantedBy = if cfg.firmware-migration-service.enable then [ "multi-user.target" ] else [ ];
|
|
||||||
serviceConfig =
|
|
||||||
let
|
|
||||||
firmware-path = "/boot/firmware";
|
|
||||||
kernel-params = pkgs.writeTextFile {
|
|
||||||
name = "cmdline.txt";
|
|
||||||
text = ''
|
|
||||||
${lib.strings.concatStringsSep " " config.boot.kernelParams}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
Type = "oneshot";
|
|
||||||
MountImages =
|
|
||||||
"/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}";
|
|
||||||
StateDirectory = "raspberrypi-firmware";
|
|
||||||
ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" ''
|
|
||||||
shopt -s nullglob
|
|
||||||
|
|
||||||
TARGET_FIRMWARE_DIR="${firmware-path}"
|
|
||||||
TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
|
|
||||||
TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
|
|
||||||
KERNEL="${kernel}/${config.system.boot.loader.kernelFile}"
|
|
||||||
SHOULD_UBOOT=${if cfg.uboot.enable then "1" else "0"}
|
|
||||||
SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot"
|
|
||||||
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
|
|
||||||
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
|
|
||||||
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
|
|
||||||
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
|
|
||||||
SRC_OVERLAYS_DIR="$SRC_FIRMWARE_DIR/overlays"
|
|
||||||
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
|
|
||||||
CONFIG="${config.hardware.raspberry-pi.config-output}"
|
|
||||||
|
|
||||||
${lib.strings.optionalString cfg.uboot.enable ''
|
|
||||||
UBOOT="${cfg.uboot.package}/u-boot.bin"
|
|
||||||
|
|
||||||
migrate_uboot() {
|
|
||||||
echo "migrating uboot"
|
|
||||||
touch "$STATE_DIRECTORY/uboot-migration-in-progress"
|
|
||||||
cp "$UBOOT" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.bin"
|
|
||||||
echo "${builtins.toString cfg.uboot.package}" > "$STATE_DIRECTORY/uboot-version"
|
|
||||||
rm "$STATE_DIRECTORY/uboot-migration-in-progress"
|
|
||||||
}
|
|
||||||
''}
|
|
||||||
|
|
||||||
migrate_kernel() {
|
|
||||||
echo "migrating kernel"
|
|
||||||
touch "$STATE_DIRECTORY/kernel-migration-in-progress"
|
|
||||||
cp "$KERNEL" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img"
|
|
||||||
cp "${initrd}" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/initrd"
|
|
||||||
echo "${
|
|
||||||
builtins.toString kernel
|
|
||||||
}" > "$STATE_DIRECTORY/kernel-version"
|
|
||||||
rm "$STATE_DIRECTORY/kernel-migration-in-progress"
|
|
||||||
}
|
|
||||||
|
|
||||||
migrate_cmdline() {
|
|
||||||
echo "migrating cmdline"
|
|
||||||
touch "$STATE_DIRECTORY/cmdline-migration-in-progress"
|
|
||||||
cp "${kernel-params}" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/cmdline.txt"
|
|
||||||
echo "${
|
|
||||||
builtins.toString kernel-params
|
|
||||||
}" > "$STATE_DIRECTORY/cmdline-version"
|
|
||||||
rm "$STATE_DIRECTORY/cmdline-migration-in-progress"
|
|
||||||
}
|
|
||||||
|
|
||||||
migrate_config() {
|
|
||||||
echo "migrating config.txt"
|
|
||||||
touch "$STATE_DIRECTORY/config-migration-in-progress"
|
|
||||||
cp "$CONFIG" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt"
|
|
||||||
echo "${config.hardware.raspberry-pi.config-output}" > "$STATE_DIRECTORY/config-version"
|
|
||||||
rm "$STATE_DIRECTORY/config-migration-in-progress"
|
|
||||||
}
|
|
||||||
|
|
||||||
migrate_firmware() {
|
|
||||||
echo "migrating raspberrypi firmware"
|
|
||||||
touch "$STATE_DIRECTORY/firmware-migration-in-progress"
|
|
||||||
for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}"
|
|
||||||
do
|
|
||||||
cp "$SRC" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ! -d "$TARGET_OVERLAYS_DIR" ]]; then
|
|
||||||
mkdir "$TARGET_OVERLAYS_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for SRC in "''${SRC_OVERLAYS[@]}"
|
|
||||||
do
|
|
||||||
cp "$SRC" "$TMPFILE"
|
|
||||||
mv -T "$TMPFILE" "$TARGET_OVERLAYS_DIR/$(basename "$SRC")"
|
|
||||||
done
|
|
||||||
echo "${
|
|
||||||
builtins.toString pkgs.raspberrypifw
|
|
||||||
}" > "$STATE_DIRECTORY/firmware-version"
|
|
||||||
rm "$STATE_DIRECTORY/firmware-migration-in-progress"
|
|
||||||
}
|
|
||||||
|
|
||||||
${lib.strings.optionalString cfg.uboot.enable ''
|
|
||||||
if [[ "$SHOULD_UBOOT" -eq 1 ]] && [[ -f "$STATE_DIRECTORY/uboot-migration-in-progress" || ! -f "$STATE_DIRECTORY/uboot-version" || $(< "$STATE_DIRECTORY/uboot-version") != ${
|
|
||||||
builtins.toString cfg.uboot.package
|
|
||||||
} ]]; then
|
|
||||||
migrate_uboot
|
|
||||||
fi
|
|
||||||
''}
|
|
||||||
|
|
||||||
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/kernel-version" || $(< "$STATE_DIRECTORY/kernel-version") != ${
|
|
||||||
builtins.toString kernel
|
|
||||||
} ]]; then
|
|
||||||
migrate_kernel
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/cmdline-version" || $(< "$STATE_DIRECTORY/cmdline-version") != ${
|
|
||||||
builtins.toString kernel-params
|
|
||||||
} ]]; then
|
|
||||||
migrate_cmdline
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$STATE_DIRECTORY/config-migration-in-progress" || ! -f "$STATE_DIRECTORY/config-version" || $(< "$STATE_DIRECTORY/config-version") != ${
|
|
||||||
builtins.toString config.hardware.raspberry-pi.config-output
|
|
||||||
} ]]; then
|
|
||||||
migrate_config
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$STATE_DIRECTORY/firmware-migration-in-progress" || ! -f "$STATE_DIRECTORY/firmware-version" || $(< "$STATE_DIRECTORY/firmware-version") != ${
|
|
||||||
builtins.toString pkgs.raspberrypifw
|
|
||||||
} ]]; then
|
|
||||||
migrate_firmware
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Default config.txt on Raspberry Pi OS:
|
# Default config.txt on Raspberry Pi OS:
|
||||||
# https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
|
# https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
|
||||||
hardware.raspberry-pi.config = {
|
hardware.raspberry-pi.config = {
|
||||||
|
|
@ -245,11 +113,9 @@ in
|
||||||
};
|
};
|
||||||
all = {
|
all = {
|
||||||
options = {
|
options = {
|
||||||
# The firmware will start our u-boot binary rather than a
|
|
||||||
# linux kernel.
|
|
||||||
kernel = {
|
kernel = {
|
||||||
enable = true;
|
enable = true;
|
||||||
value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img";
|
value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else kernelBootPath;
|
||||||
};
|
};
|
||||||
ramfsfile = {
|
ramfsfile = {
|
||||||
enable = !cfg.uboot.enable;
|
enable = !cfg.uboot.enable;
|
||||||
|
|
@ -318,13 +184,15 @@ in
|
||||||
};
|
};
|
||||||
boot = {
|
boot = {
|
||||||
kernelParams =
|
kernelParams =
|
||||||
if cfg.uboot.enable then [ ]
|
[ "console=serial0,115200n8" "console=tty1" ] ++
|
||||||
|
(if cfg.uboot.enable then [ ]
|
||||||
else [
|
else [
|
||||||
"console=tty1"
|
"root=PARTUUID=${cfg.rootGPUID}"
|
||||||
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
|
"rootfstype=ext4"
|
||||||
"console=serial0,115200n8"
|
"fsck.repair=yes"
|
||||||
"init=/sbin/init"
|
"rootwait"
|
||||||
];
|
"init=/nix/var/nix/profiles/system/init"
|
||||||
|
]);
|
||||||
initrd = {
|
initrd = {
|
||||||
availableKernelModules = [
|
availableKernelModules = [
|
||||||
"usbhid"
|
"usbhid"
|
||||||
|
|
@ -337,12 +205,43 @@ in
|
||||||
kernelPackages = pkgs.linuxPackagesFor pkgs.rpi-kernels."${version}"."${board}";
|
kernelPackages = pkgs.linuxPackagesFor pkgs.rpi-kernels."${version}"."${board}";
|
||||||
loader = {
|
loader = {
|
||||||
grub.enable = lib.mkDefault false;
|
grub.enable = lib.mkDefault false;
|
||||||
initScript.enable = !cfg.uboot.enable;
|
|
||||||
generic-extlinux-compatible = {
|
generic-extlinux-compatible.enable = false;
|
||||||
enable = lib.mkDefault cfg.uboot.enable;
|
generic-extlinux-compatible-pi-loader = {
|
||||||
|
# extlinux-style boot is only used when uboot is enabled
|
||||||
|
# when uboot is disabled, use this module to put files into
|
||||||
|
# the boot partition as part of installBootloader
|
||||||
|
enable = true;
|
||||||
# We want to use the device tree provided by firmware, so don't
|
# We want to use the device tree provided by firmware, so don't
|
||||||
# add FDTDIR to the extlinux conf file.
|
# add FDTDIR to the extlinux conf file.
|
||||||
useGenerationDeviceTree = false;
|
useGenerationDeviceTree = false;
|
||||||
|
extraCommandsAfter = let
|
||||||
|
configTxt = config.hardware.raspberry-pi.config-output;
|
||||||
|
kernelParams = pkgs.writeTextFile {
|
||||||
|
name = "cmdline.txt";
|
||||||
|
text = ''
|
||||||
|
${lib.strings.concatStringsSep " " config.boot.kernelParams}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
script = flip concatMapStrings config.boot.loader.generic-extlinux-compatible-pi-loader.mirroredBoots (args: ''
|
||||||
|
# Add raspi files
|
||||||
|
cd ${pkgs.raspberrypifw}/share/raspberrypi/boot
|
||||||
|
${atomicCopySafe} bootcode.bin ${args.path}/bootcode.bin
|
||||||
|
${atomicCopySafe} overlays ${args.path}/overlays
|
||||||
|
${pkgs.findutils}/bin/find . -type f -name 'fixup*.dat' -exec ${atomicCopySafe} {} ${args.path}/{} \;
|
||||||
|
${pkgs.findutils}/bin/find . -type f -name 'start*.elf' -exec ${atomicCopySafe} {} ${args.path}/{} \;
|
||||||
|
${pkgs.findutils}/bin/find . -type f -name '*.dtb' -exec ${atomicCopySafe} {} ${args.path}/{} \;
|
||||||
|
|
||||||
|
# Add config.txt
|
||||||
|
${atomicCopyClobber} ${configTxt} ${args.path}/config.txt
|
||||||
|
'' + (if cfg.uboot.enable then ''
|
||||||
|
# Add u-boot files
|
||||||
|
${atomicCopySafe} ${cfg.uboot.package}/u-boot.bin ${args.path}/u-boot-rpi-arm64.bin
|
||||||
|
'' else ''
|
||||||
|
# Add kernel params
|
||||||
|
${atomicCopyClobber} ${kernelParams} ${args.path}/cmdline.txt
|
||||||
|
''));
|
||||||
|
in [ (toString (pkgs.writeShellScript "cp-pi-loaders.sh" script)) ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue