migrate the nix install to an external USB drive.

this requires a patch to uboot:
- uboot thinks the drive has a capacity of 0 (i.e. 'unknown'). unclear precisely why. could be noncompliant drive firmware, or a timeout somewhere.

and a patch to the rpi bootloader:
- in order to trampoline into the rpi-4 uboot.

and custom kernel modules in the initrd:
- in order to detect the USB hub (rpi fw).

additionally, i'm MANUALLY placing `bcm2711-rpi-400.dtb` into `/boot/nixos/..-linux-5.10.111-dtbs/broadcom`.
i'll want to do this automatically over time.

i hope to simplify much of this over time: this is just the first thing which works after a couple days of hacking at it.
This commit is contained in:
Colin 2022-05-17 01:58:12 +00:00
parent aeb8319154
commit 1064867194
23 changed files with 747 additions and 103 deletions

View File

@ -1,27 +1,57 @@
{ config, pkgs, lib, ... }:
{
fileSystems."/" = {
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
fsType = "ext4";
};
# fileSystems."/" = {
# device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
# fsType = "ext4";
# };
fileSystems."/mnt/storage" = {
fileSystems."/" = {
device = "/dev/disk/by-uuid/2be70d38-79f4-41b6-bee2-bce5a25f8f7b";
fsType = "ext4";
};
fileSystems."/boot" = {
# this is the /dev/sda1 boot device.
# by mounting this in boot, we can then run `nixos-rebuild` and it'll only take affect when booting from sda1
# (old mmc1 boot will be preserved)
device = "/dev/disk/by-uuid/B318-A67E";
fsType = "vfat";
};
# fileSystems."/mnt/storage" = {
# device = "/dev/disk/by-uuid/2be70d38-79f4-41b6-bee2-bce5a25f8f7b";
# fsType = "ext4";
# };
# temporary; nix porting
# fileSystems."/home/colin" = {
# device = "/mnt/storage/home/colin";
# options = [ "bind" ];
# };
# fileSystems."/boot" = {
# device = "/mnt/storage/boot";
# options = [ "bind" ];
# };
# fileSystems."/var/spool" = {
# device = "/mnt/storage/var/spool";
# options = [ "bind" ];
# };
# fileSystems."/var/lib" = {
# device = "/mnt/storage/var/lib";
# options = [ "bind" ];
# };
fileSystems."/var/lib/pleroma" = {
device = "/mnt/storage/opt/pleroma.nix";
device = "/opt/pleroma";
options = [ "bind" ];
};
fileSystems."/var/lib/transmission/Downloads" = {
device = "/mnt/storage/opt/uninsane/media";
device = "/opt/uninsane/media";
options = [ "bind" ];
};
fileSystems."/var/lib/transmission/.incomplete" = {
device = "/mnt/storage/opt/uninsane/media/incomplete";
device = "/opt/uninsane/media/incomplete";
options = [ "bind" ];
};

View File

@ -3,6 +3,14 @@
{
networking.domain = "uninsane.org";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# TODO: how to disable entirely?
networking.interfaces.wlan0.useDHCP = false;
# networking.firewall.enable = false;
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [

View File

@ -9,6 +9,7 @@
# web-created keys are allowed to delete files, which you probably don't want for an incremental backup program
services.duplicity.targetUrl = builtins.replaceStrings ["\n"] [""] (builtins.readFile /etc/nixos/secrets/duplicity_url);
# format: PASSPHRASE=<cleartext>
# two sisters
services.duplicity.secretFile = /etc/nixos/secrets/duplicity_env;
# NB: manually trigger with `systemctl start duplicity`
services.duplicity.frequency = "daily";
@ -24,7 +25,7 @@
"/var/lib/transmission/Downloads"
"/var/lib/transmission/.incomplete"
# data that's not worth the cost to backup:
"/mnt/storage/opt/uninsane/media"
"/opt/uninsane/media"
];
# set this for the FIRST backup, then remove it to enable incremental backups

View File

@ -72,7 +72,7 @@
# IRC bridging
# note: Rizon allows only FOUR simultaneous IRC connections per IP: https://wiki.rizon.net/index.php?title=Connection/Session_Limit_Exemptions
# Rizon supports CertFP for auth: https://wiki.rizon.net/index.php?title=CertFP
services.matrix-appservice-irc.enable = true;
# services.matrix-appservice-irc.enable = true;
services.matrix-appservice-irc.registrationUrl = "http://127.0.0.1:8009";
# settings documented here: https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml
services.matrix-appservice-irc.settings = {
@ -136,15 +136,15 @@
};
# hardcoded mappings, for when dynamicChannels fails us. TODO: probably safe to remove these.
mappings = {
"#chat" = {
roomIds = [ "!GXJSOTdbtxRboGtDep:uninsane.org" ];
};
# BakaBT requires account registration, which i think means my user needs to be added before the appservice user
"#BakaBT" = {
roomIds = [ "!feZKttuYuHilqPFSkD:uninsane.org" ];
};
};
# mappings = {
# "#chat" = {
# roomIds = [ "!GXJSOTdbtxRboGtDep:uninsane.org" ];
# };
# # BakaBT requires account registration, which i think means my user needs to be added before the appservice user
# "#BakaBT" = {
# roomIds = [ "!feZKttuYuHilqPFSkD:uninsane.org" ];
# };
# };
# for per-user IRC password:
# invite @irc_rizon_NickServ:uninsane.org to a DM and type `help` => register
# invite the matrix-appservice-irc user to a DM and type `!help` => add PW to database

View File

@ -6,7 +6,7 @@
# web blog/personal site
services.nginx.virtualHosts."uninsane.org" = {
root = "/mnt/storage/opt/uninsane/root";
root = "/opt/uninsane/root";
addSSL = true;
enableACME = true;

View File

@ -2,7 +2,7 @@
{
services.postgresql.enable = true;
services.postgresql.dataDir = "/mnt/storage/opt/postgresql/13";
services.postgresql.dataDir = "/opt/postgresql/13";
# XXX colin: for a proper deploy, we'd want to include something for Pleroma here too.
# services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
# CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD '<password goes here>';

View File

@ -13,7 +13,7 @@
rpc-password = "{503fc8928344f495efb8e1f955111ca5c862ce0656SzQnQ5";
rpc-whitelist-enabled = false;
# download-dir = "/mnt/storage/opt/uninsane/media/";
# download-dir = "/opt/uninsane/media/";
# force peer connections to be encrypted
encryption = 2;

View File

@ -28,6 +28,7 @@
pkgs.fd
pkgs.file
pkgs.git
pkgs.gptfdisk
pkgs.htop
pkgs.iftop
pkgs.iotop
@ -39,6 +40,8 @@
pkgs.netcat
pkgs.nettools
pkgs.nmap
pkgs.parted
pkgs.python3
pkgs.ripgrep
pkgs.socat
pkgs.sudo
@ -71,8 +74,9 @@
];
};
# Automatically log in at the virtual consoles.
services.getty.autologinUser = "colin";
# automatically log in at the virtual consoles.
# using root here makes sure we always have an escape hatch
services.getty.autologinUser = "root";
security.sudo = {
enable = true;

View File

@ -2,7 +2,7 @@
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
{ config, lib, modulesPath, pkgs, specialArgs, options }:
let
pkgsUnstable = import (builtins.fetchTarball {
@ -16,7 +16,10 @@ let
}) {};
in
{
imports = [ ./cfg ];
imports = [
./cfg
./modules
];
nixpkgs.overlays = [
(self: super: {
@ -31,92 +34,55 @@ in
# https://github.com/go-gitea/gitea/pull/19119
# safe to remove after 1.16.5 (or 1.16.7 if we need db compat?)
gitea = pkgsUnstable.gitea;
# try a newer rpi4 u-boot
# ubootRaspberryPi4_64bit = pkgsUnstable.ubootRaspberryPi4_64bit;
ubootRaspberryPi4_64bit = self.callPackage ./pkgs/ubootRaspberryPi4_64bit { pkgs = super; };
})
];
# XXX colin: UNMODIFIED DEFAULTS BELOW
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
# NixOS defaults to grub: we don't want that.
boot.loader.grub.enable = false;
# Enables the generation of /boot/extlinux/extlinux.conf
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.raspberryPiColin.enable = true;
boot.loader.raspberryPiColin.uboot.enable = true;
boot.loader.raspberryPiColin.version = 4;
# networking.hostName = "nixos"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
networking.interfaces.wlan0.useDHCP = true;
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
# i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Configure keymap in X11
# services.xserver.layout = "us";
# services.xserver.xkbOptions = "eurosign:e";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# sound.enable = true;
# hardware.pulseaudio.enable = true;
# Enable touchpad support (enabled default in most desktopManager).
# services.xserver.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# users.users.jane = {
# isNormalUser = true;
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# };
# List packages installed in system profile. To search, run:
# $ nix search wget
# environment.systemPackages = with pkgs; [
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
# firefox
boot.initrd.availableKernelModules = [
"bcm2711_thermal"
"bcm_phy_lib"
"brcmfmac"
"brcmutil"
"broadcom"
"clk_raspberrypi"
"drm" # Direct Render Manager
"enclosure" # SCSI ?
"fuse"
"mdio_bcm_unimac"
"pcie_brcmstb"
"raspberrypi_cpufreq"
"raspberrypi_hwmon"
"ses" # SCSI Enclosure Services
"uas" # USB attached storage
"uio" # userspace IO
"uio_pdrv_genirq"
"xhci_pci"
"xhci_pci_renesas"
];
boot.initrd.compressor = "gzip"; # defaults to zstd
# hack in the `boot.shell_on_fail` arg since it doesn't seem to work otherwise
boot.initrd.preFailCommands = "allowShell=1";
# default: 4 (warn). 7 is debug
# boot.consoleLogLevel = 7;
# boot.kernelParams = [
# "boot.shell_on_fail"
# # "boot.trace"
# # "systemd.log_level=debug"
# # "systemd.log_target=console"
# ];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions

5
modules/default.nix Normal file
View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
imports = [ ./system ];
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
imports = [ ./loader ];
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
imports = [ ./raspberrypi/raspberrypi.nix ];
}

View 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;
}

View File

@ -0,0 +1,157 @@
#! @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
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

View File

@ -0,0 +1,9 @@
{ pkgs, configTxt, firmware ? pkgs.raspberrypifw }:
pkgs.substituteAll {
src = ./raspberrypi-builder.sh;
isExecutable = true;
inherit (pkgs) bash;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
inherit firmware configTxt;
}

View File

@ -0,0 +1,143 @@
#! @bash@/bin/sh
# This can end up being called disregarding the shebang.
set -e
shopt -s nullglob
export PATH=/empty
for i in @path@; do PATH=$PATH:$i/bin; done
usage() {
echo "usage: $0 -c <path-to-default-configuration> [-d <boot-dir>]" >&2
exit 1
}
default= # Default configuration
target=/boot # Target directory
while getopts "c:d:" opt; do
case "$opt" in
c) default="$OPTARG" ;;
d) target="$OPTARG" ;;
\?) usage ;;
esac
done
echo "updating the boot generations directory..."
mkdir -p $target/old
# 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/kernels.
declare -A filesCopied
copyToKernelsDir() {
local src="$1"
local dst="$target/old/$(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 $src $dstTmp
mv $dstTmp $dst
fi
filesCopied[$dst]=1
result=$dst
}
copyForced() {
local src="$1"
local dst="$2"
cp $src $dst.tmp
mv $dst.tmp $dst
}
outdir=$target/old
mkdir -p $outdir || true
# Copy its kernel and initrd to $target/old.
addEntry() {
local path="$1"
local generation="$2"
if ! test -e $path/kernel -a -e $path/initrd; then
return
fi
local kernel=$(readlink -f $path/kernel)
local initrd=$(readlink -f $path/initrd)
local dtb_path=$(readlink -f $path/dtbs)
if test -n "@copyKernels@"; then
copyToKernelsDir $kernel; kernel=$result
copyToKernelsDir $initrd; initrd=$result
fi
echo $(readlink -f $path) > $outdir/$generation-system
echo $(readlink -f $path/init) > $outdir/$generation-init
cp $path/kernel-params $outdir/$generation-cmdline.txt
echo $initrd > $outdir/$generation-initrd
echo $kernel > $outdir/$generation-kernel
if test "$generation" = "default"; then
copyForced $kernel $target/kernel.img
copyForced $initrd $target/initrd
for dtb in $dtb_path/{broadcom,}/bcm*.dtb; do
dst="$target/$(basename $dtb)"
copyForced $dtb "$dst"
filesCopied[$dst]=1
done
cp "$(readlink -f "$path/init")" $target/nixos-init
echo "`cat $path/kernel-params` init=$path/init" >$target/cmdline.txt
fi
}
addEntry $default default
# Add all 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); do
link=/nix/var/nix/profiles/system-$generation-link
addEntry $link $generation
done
# Add the firmware files
fwdir=@firmware@/share/raspberrypi/boot/
copyForced $fwdir/bootcode.bin $target/bootcode.bin
copyForced $fwdir/fixup.dat $target/fixup.dat
copyForced $fwdir/fixup4.dat $target/fixup4.dat
copyForced $fwdir/fixup4cd.dat $target/fixup4cd.dat
copyForced $fwdir/fixup4db.dat $target/fixup4db.dat
copyForced $fwdir/fixup4x.dat $target/fixup4x.dat
copyForced $fwdir/fixup_cd.dat $target/fixup_cd.dat
copyForced $fwdir/fixup_db.dat $target/fixup_db.dat
copyForced $fwdir/fixup_x.dat $target/fixup_x.dat
copyForced $fwdir/start.elf $target/start.elf
copyForced $fwdir/start4.elf $target/start4.elf
copyForced $fwdir/start4cd.elf $target/start4cd.elf
copyForced $fwdir/start4db.elf $target/start4db.elf
copyForced $fwdir/start4x.elf $target/start4x.elf
copyForced $fwdir/start_cd.elf $target/start_cd.elf
copyForced $fwdir/start_db.elf $target/start_db.elf
copyForced $fwdir/start_x.elf $target/start_x.elf
# Add the config.txt
copyForced @configTxt@ $target/config.txt
# Remove obsolete files from $target and $target/old.
for fn in $target/old/*linux* $target/old/*initrd-initrd* $target/bcm*.dtb; do
if ! test "${filesCopied[$fn]}" = 1; then
rm -vf -- "$fn"
fi
done

View File

@ -0,0 +1,101 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.boot.loader.raspberryPiColin;
builderUboot = import ./uboot-builder.nix { inherit pkgs configTxt; inherit (cfg) version; };
builderGeneric = import ./raspberrypi-builder.nix { inherit pkgs configTxt; };
builder =
if cfg.uboot.enable then
"${builderUboot} -g ${toString cfg.uboot.configurationLimit} -t ${timeoutStr} -c"
else
"${builderGeneric} -c";
blCfg = config.boot.loader;
timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
isAarch64 = pkgs.stdenv.hostPlatform.isAarch64;
optional = pkgs.lib.optionalString;
configTxt =
pkgs.writeText "config.txt" (''
# U-Boot used to need this to work, regardless of whether UART is actually used or not.
# TODO: check when/if this can be removed.
enable_uart=1
# Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
# when attempting to show low-voltage or overtemperature warnings.
avoid_warnings=1
'' + optional isAarch64 ''
# Boot in 64-bit mode.
arm_64bit=1
'' + (if cfg.uboot.enable then ''
kernel=u-boot-rpi.bin
'' else ''
kernel=kernel.img
initramfs initrd followkernel
'') + optional (cfg.firmwareConfig != null) cfg.firmwareConfig);
in
{
options = {
boot.loader.raspberryPiColin = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Whether to create files with the system generations in
<literal>/boot</literal>.
<literal>/boot/old</literal> will hold files from old generations.
'';
};
version = mkOption {
default = 2;
type = types.enum [ 0 1 2 3 4 ];
description = "";
};
uboot = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Enable using uboot as bootmanager for the raspberry pi.
'';
};
configurationLimit = mkOption {
default = 20;
example = 10;
type = types.int;
description = ''
Maximum number of configurations in the boot menu.
'';
};
};
firmwareConfig = mkOption {
default = null;
type = types.nullOr types.lines;
description = ''
Extra options that will be appended to <literal>/boot/config.txt</literal> file.
For possible values, see: https://www.raspberrypi.org/documentation/configuration/config-txt/
'';
};
};
};
config = mkIf cfg.enable {
system.build.installBootLoader = builder;
system.boot.loader.id = "raspberrypi";
system.boot.loader.kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target;
};
}

View File

@ -0,0 +1,41 @@
{ pkgs, version, configTxt }:
let
isAarch64 = pkgs.stdenv.hostPlatform.isAarch64;
uboot =
if version == 0 then
pkgs.ubootRaspberryPiZero
else if version == 1 then
pkgs.ubootRaspberryPi
else if version == 2 then
pkgs.ubootRaspberryPi2
else if version == 3 then
if isAarch64 then
pkgs.ubootRaspberryPi3_64bit
else
pkgs.ubootRaspberryPi3_32bit
else if version == 4 then
if isAarch64 then
pkgs.ubootRaspberryPi4_64bit
else
pkgs.ubootRaspberryPi4_32bit
else
throw "U-Boot is only supported on the raspberry pi {1,2,3,4}.";
extlinuxConfBuilder =
import ../generic-extlinux-compatible/extlinux-conf-builder.nix {
pkgs = pkgs.buildPackages;
};
in
pkgs.substituteAll {
src = ./uboot-builder.sh;
isExecutable = true;
inherit (pkgs) bash;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
firmware = pkgs.raspberrypifw;
inherit uboot;
inherit configTxt;
inherit extlinuxConfBuilder;
inherit version;
}

View File

@ -0,0 +1,38 @@
#! @bash@/bin/sh -e
target=/boot # Target directory
while getopts "t:c:d:g:" opt; do
case "$opt" in
d) target="$OPTARG" ;;
*) ;;
esac
done
copyForced() {
local src="$1"
local dst="$2"
cp $src $dst.tmp
mv $dst.tmp $dst
}
# Call the extlinux builder
"@extlinuxConfBuilder@" "$@"
# Add the firmware files
fwdir=@firmware@/share/raspberrypi/boot/
copyForced $fwdir/bootcode.bin $target/bootcode.bin
copyForced $fwdir/fixup.dat $target/fixup.dat
copyForced $fwdir/fixup_cd.dat $target/fixup_cd.dat
copyForced $fwdir/fixup_db.dat $target/fixup_db.dat
copyForced $fwdir/fixup_x.dat $target/fixup_x.dat
copyForced $fwdir/start.elf $target/start.elf
copyForced $fwdir/start_cd.elf $target/start_cd.elf
copyForced $fwdir/start_db.elf $target/start_db.elf
copyForced $fwdir/start_x.elf $target/start_x.elf
# Add the uboot file
copyForced @uboot@/u-boot.bin $target/u-boot-rpi.bin
# Add the config.txt
copyForced @configTxt@ $target/config.txt

View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
imports = [ ./boot ];
}

View File

@ -1,7 +1,7 @@
{ pkgs }:
(pkgs.jackett.overrideAttrs (upstream: {
patches = [
patches = (upstream.patches or []) ++ [
# bind to an IP address which is usable behind a netns
./01-fix-bind-host.patch
];

View File

@ -0,0 +1,109 @@
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index eae03bf023..2ded4123ce 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -63,3 +63,11 @@ CONFIG_VIDEO_BCM2835=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_CMD_CONFIG=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_LOG=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_LOG_MAX_LEVEL=8
+CONFIG_CMD_LSBLK=y
diff --git a/disk/part.c b/disk/part.c
index 79955c7fb0..c1d469cebb 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -15,7 +15,7 @@
#include <part.h>
#include <ubifs_uboot.h>
-#undef PART_DEBUG
+#define PART_DEBUG
#ifdef PART_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 829ccb6bd1..5f3f0ae042 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -133,12 +133,12 @@ static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
* Check that the first_usable_lba and that the last_usable_lba are
* within the disk.
*/
- if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) {
+ if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba && lastlba != 0) {
printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n",
le64_to_cpu(gpt_h->first_usable_lba), lastlba);
return -1;
}
- if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) {
+ if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba && lastlba != 0) {
printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n",
le64_to_cpu(gpt_h->last_usable_lba), lastlba);
return -1;
@@ -1044,6 +1044,8 @@ static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
return 2;
}
+ printf("is_gpt_valid: sig, lba0, lbaend %llx %llx %llx\n", pgpt_head->signature, pgpt_head->first_usable_lba, pgpt_head->last_usable_lba);
+
if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
return 0;
@@ -1088,6 +1090,7 @@ static int find_valid_gpt(struct blk_desc *dev_desc, gpt_header *gpt_head,
gpt_entry **pgpt_pte)
{
int r;
+ printf("find_valid_gpt %s\n", dev_desc->vendor);
r = is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head,
pgpt_pte);
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 21c5209bb6..6ce03d8d09 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -443,6 +443,8 @@ unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
const struct blk_ops *ops = blk_get_ops(dev);
ulong blks_read;
+ printf("blk_dread %s %llu %llu\n", block_dev->vendor, start, blkcnt);
+
if (!ops->read)
return -ENOSYS;
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index 7a5f0851b5..01545f7480 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -15,6 +15,8 @@
/* Architecture, CPU, etc.*/
+#define CONFIG_SYS_64BIT_LBA
+
/* Use SoC timer for AArch32, but architected timer for AArch64 */
#ifndef CONFIG_ARM64
#define CONFIG_SYS_TIMER_RATE 1000000
diff --git a/include/log.h b/include/log.h
index 8f35c10abb..afd2d704f4 100644
--- a/include/log.h
+++ b/include/log.h
@@ -241,11 +241,7 @@ int _log_buffer(enum log_category_t cat, enum log_level_t level,
__func__, pr_fmt(_fmt), ##_args); \
})
-#ifdef DEBUG
#define _DEBUG 1
-#else
-#define _DEBUG 0
-#endif
#ifdef CONFIG_SPL_BUILD
#define _SPL_BUILD 1

View File

@ -0,0 +1,9 @@
{ pkgs }:
(pkgs.ubootRaspberryPi4_64bit.overrideAttrs (upstream: {
patches = (upstream.patches or []) ++ [
# enable booting from > 2 TiB drives
./01-enable-large-gpt.patch
];
}))