mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-26 08:53:21 +00:00
Merge pull request #8978 from dezgeg/pr-arm-images
ARM SD card image expressions
This commit is contained in:
commit
982ce5ed58
88
nixos/lib/make-ext4-fs.nix
Normal file
88
nixos/lib/make-ext4-fs.nix
Normal file
@ -0,0 +1,88 @@
|
||||
# Builds an ext4 image containing a populated /nix/store with the closure
|
||||
# of store paths passed in the storePaths parameter. The generated image
|
||||
# is sized to only fit its contents, with the expectation that a script
|
||||
# resizes the filesystem at boot time.
|
||||
{ pkgs
|
||||
, storePaths
|
||||
, volumeLabel
|
||||
}:
|
||||
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "ext4-fs.img";
|
||||
|
||||
buildInputs = with pkgs; [e2fsprogs libfaketime perl];
|
||||
|
||||
# For obtaining the closure of `storePaths'.
|
||||
exportReferencesGraph =
|
||||
map (x: [("closure-" + baseNameOf x) x]) storePaths;
|
||||
|
||||
buildCommand =
|
||||
''
|
||||
# Add the closures of the top-level store objects.
|
||||
storePaths=$(perl ${pkgs.pathsFromGraph} closure-*)
|
||||
|
||||
# Also include a manifest of the closures in a format suitable
|
||||
# for nix-store --load-db.
|
||||
printRegistration=1 perl ${pkgs.pathsFromGraph} closure-* > nix-path-registration
|
||||
|
||||
# Make a crude approximation of the size of the target image.
|
||||
# If the script starts failing, increase the fudge factors here.
|
||||
numInodes=$(find $storePaths | wc -l)
|
||||
numDataBlocks=$(du -c -B 4096 --apparent-size $storePaths | awk '$2 == "total" { print int($1 * 1.03) }')
|
||||
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
|
||||
echo "Creating an EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
|
||||
|
||||
truncate -s $bytes $out
|
||||
faketime "1970-01-01 00:00:00" mkfs.ext4 -L ${volumeLabel} -U 44444444-4444-4444-8888-888888888888 $out
|
||||
|
||||
# Populate the image contents by piping a bunch of commands to the `debugfs` tool from e2fsprogs.
|
||||
# For example, to copy /nix/store/abcd...efg-coreutils-8.23/bin/sleep:
|
||||
# cd /nix/store/abcd...efg-coreutils-8.23/bin
|
||||
# write /nix/store/abcd...efg-coreutils-8.23/bin/sleep sleep
|
||||
# sif sleep mode 040555
|
||||
# sif sleep gid 30000
|
||||
# In particular, debugfs doesn't handle absolute target paths; you have to 'cd' in the virtual
|
||||
# filesystem first. Likewise the intermediate directories must already exist (using `find`
|
||||
# handles that for us). And when setting the file's permissions, the inode type flags (__S_IFDIR,
|
||||
# __S_IFREG) need to be set as well.
|
||||
(
|
||||
echo write nix-path-registration nix-path-registration
|
||||
echo mkdir nix
|
||||
echo cd /nix
|
||||
echo mkdir store
|
||||
|
||||
# XXX: This explodes in exciting ways if anything in /nix/store has a space in it.
|
||||
find $storePaths -printf '%y %f %h %m\n'| while read -r type file dir perms; do
|
||||
# echo "TYPE=$type DIR=$dir FILE=$file PERMS=$perms" >&2
|
||||
|
||||
echo "cd $dir"
|
||||
case $type in
|
||||
d)
|
||||
echo "mkdir $file"
|
||||
echo sif $file mode $((040000 | 0$perms)) # magic constant is __S_IFDIR
|
||||
;;
|
||||
f)
|
||||
echo "write $dir/$file $file"
|
||||
echo sif $file mode $((0100000 | 0$perms)) # magic constant is __S_IFREG
|
||||
;;
|
||||
l)
|
||||
echo "symlink $file $(readlink "$dir/$file")"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown entry: $type $dir $file $perms" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo sif $file gid 30000 # chgrp to nixbld
|
||||
done
|
||||
) | faketime "1970-01-01 00:00:00" debugfs -w $out -f /dev/stdin > errorlog 2>&1
|
||||
|
||||
# The debugfs tool doesn't terminate on error nor exit with a non-zero status. Check manually.
|
||||
if egrep -q 'Could not allocate|File not found' errorlog; then
|
||||
cat errorlog
|
||||
echo "--- Failed to create EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks) ---"
|
||||
return 1
|
||||
fi
|
||||
'';
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
extlinux-conf-builder =
|
||||
import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
|
||||
inherit pkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../profiles/minimal.nix
|
||||
../../profiles/installation-device.nix
|
||||
./sd-image.nix
|
||||
];
|
||||
|
||||
assertions = lib.singleton {
|
||||
assertion = pkgs.stdenv.system == "armv7l-linux";
|
||||
message = "sd-image-armv7l-multiplatform.nix can be only built natively on ARMv7; " +
|
||||
"it cannot be cross compiled";
|
||||
};
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
# FIXME: change this to linuxPackages_latest once v4.2 is out
|
||||
boot.kernelPackages = pkgs.linuxPackages_testing;
|
||||
boot.kernelParams = ["console=ttyS0,115200n8" "console=ttyAMA0,115200n8" "console=tty0"];
|
||||
|
||||
# FIXME: fix manual evaluation on ARM
|
||||
services.nixosManual.enable = lib.mkOverride 0 false;
|
||||
|
||||
# FIXME: this probably should be in installation-device.nix
|
||||
users.extraUsers.root.initialHashedPassword = "";
|
||||
|
||||
sdImage = {
|
||||
populateBootCommands = ''
|
||||
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
|
||||
'';
|
||||
};
|
||||
}
|
46
nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
Normal file
46
nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
Normal file
@ -0,0 +1,46 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
extlinux-conf-builder =
|
||||
import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
|
||||
inherit pkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../profiles/minimal.nix
|
||||
../../profiles/installation-device.nix
|
||||
./sd-image.nix
|
||||
];
|
||||
|
||||
assertions = lib.singleton {
|
||||
assertion = pkgs.stdenv.system == "armv6l-linux";
|
||||
message = "sd-image-raspberrypi.nix can be only built natively on ARMv6; " +
|
||||
"it cannot be cross compiled";
|
||||
};
|
||||
|
||||
# Needed by RPi firmware
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_rpi;
|
||||
|
||||
# FIXME: fix manual evaluation on ARM
|
||||
services.nixosManual.enable = lib.mkOverride 0 false;
|
||||
|
||||
# FIXME: this probably should be in installation-device.nix
|
||||
users.extraUsers.root.initialHashedPassword = "";
|
||||
|
||||
sdImage = {
|
||||
populateBootCommands = ''
|
||||
for f in bootcode.bin fixup.dat start.elf; do
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/$f boot/
|
||||
done
|
||||
cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi.bin
|
||||
echo 'kernel u-boot-rpi.bin' > boot/config.txt
|
||||
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
|
||||
'';
|
||||
};
|
||||
}
|
127
nixos/modules/installer/cd-dvd/sd-image.nix
Normal file
127
nixos/modules/installer/cd-dvd/sd-image.nix
Normal file
@ -0,0 +1,127 @@
|
||||
# This module creates a bootable SD card image containing the given NixOS
|
||||
# configuration. The generated image is MBR partitioned, with a FAT /boot
|
||||
# partition, and ext4 root partition. The generated image is sized to fit
|
||||
# its contents, and a boot script automatically resizes the root partition
|
||||
# to fit the device on the first boot.
|
||||
#
|
||||
# The derivation for the SD image will be placed in
|
||||
# config.system.build.sdImage
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
rootfsImage = import ../../../lib/make-ext4-fs.nix {
|
||||
inherit pkgs;
|
||||
inherit (config.sdImage) storePaths;
|
||||
volumeLabel = "NIXOS_SD";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.sdImage = {
|
||||
storePaths = mkOption {
|
||||
type = with types; listOf package;
|
||||
example = literalExample "[ pkgs.stdenv ]";
|
||||
description = ''
|
||||
Derivations to be included in the Nix store in the generated SD image.
|
||||
'';
|
||||
};
|
||||
|
||||
bootSize = mkOption {
|
||||
type = types.int;
|
||||
default = 128;
|
||||
description = ''
|
||||
Size of the /boot partition, in megabytes.
|
||||
'';
|
||||
};
|
||||
|
||||
populateBootCommands = mkOption {
|
||||
example = literalExample "'' cp \${pkgs.myBootLoader}/u-boot.bin boot/ ''";
|
||||
description = ''
|
||||
Shell commands to populate the ./boot directory.
|
||||
All files in that directory are copied to the
|
||||
/boot partition on the SD image.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/NIXOS_BOOT";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
|
||||
sdImage.storePaths = [ config.system.build.toplevel ];
|
||||
|
||||
system.build.sdImage = pkgs.stdenv.mkDerivation {
|
||||
name = "sd-image-${pkgs.stdenv.system}.img";
|
||||
|
||||
buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
|
||||
|
||||
buildCommand = ''
|
||||
# Create the image file sized to fit /boot and /, plus 4M of slack
|
||||
rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }')
|
||||
bootSizeBlocks=$((${toString config.sdImage.bootSize} * 1024 * 1024 / 512))
|
||||
imageSize=$((rootSizeBlocks * 512 + bootSizeBlocks * 512 + 4096 * 1024))
|
||||
truncate -s $imageSize $out
|
||||
|
||||
# type=b is 'W95 FAT32', type=83 is 'Linux'.
|
||||
sfdisk $out <<EOF
|
||||
label: dos
|
||||
label-id: 0x2178694e
|
||||
|
||||
start=1M, size=$bootSizeBlocks, type=b, bootable
|
||||
type=83
|
||||
EOF
|
||||
|
||||
# Copy the rootfs into the SD image
|
||||
eval $(partx $out -o START,SECTORS --nr 2 --pairs)
|
||||
dd conv=notrunc if=${rootfsImage} of=$out seek=$START count=$SECTORS
|
||||
|
||||
# Create a FAT32 /boot partition of suitable size into bootpart.img
|
||||
eval $(partx $out -o START,SECTORS --nr 1 --pairs)
|
||||
truncate -s $((SECTORS * 512)) bootpart.img
|
||||
faketime "1970-01-01 00:00:00" mkfs.vfat -i 0x2178694e -n NIXOS_BOOT bootpart.img
|
||||
|
||||
# Populate the files intended for /boot
|
||||
mkdir boot
|
||||
${config.sdImage.populateBootCommands}
|
||||
|
||||
# Copy the populated /boot into the SD image
|
||||
(cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::)
|
||||
dd conv=notrunc if=bootpart.img of=$out seek=$START count=$SECTORS
|
||||
'';
|
||||
};
|
||||
|
||||
boot.postBootCommands = ''
|
||||
# On the first boot do some maintenance tasks
|
||||
if [ -f /nix-path-registration ]; then
|
||||
# Figure out device names for the boot device and root filesystem.
|
||||
rootPart=$(readlink -f /dev/disk/by-label/NIXOS_SD)
|
||||
bootDevice=$(lsblk -npo PKNAME $rootPart)
|
||||
|
||||
# Resize the root partition and the filesystem to fit the disk
|
||||
echo ",+," | sfdisk -N2 --no-reread $bootDevice
|
||||
${pkgs.parted}/bin/partprobe
|
||||
${pkgs.e2fsprogs}/bin/resize2fs $rootPart
|
||||
|
||||
# Register the contents of the initial Nix store
|
||||
${config.nix.package}/bin/nix-store --load-db < /nix-path-registration
|
||||
|
||||
# nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
|
||||
# Prevents this from running on later boots.
|
||||
rm -f /nix-path-registration
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
@ -52,6 +52,7 @@ in
|
||||
TTYPath = "/dev/${cfg.tty}";
|
||||
TTYReset = true;
|
||||
TTYVTDisallocate = true;
|
||||
WorkingDirectory = "/tmp";
|
||||
Restart = "always";
|
||||
};
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
pkgs.substituteAll {
|
||||
src = ./extlinux-conf-builder.sh;
|
||||
isExecutable = true;
|
||||
inherit (pkgs) bash;
|
||||
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
|
||||
inherit (pkgs) bash;
|
||||
kernelDTB = pkgs.stdenv.platform.kernelDTB or false;
|
||||
}
|
||||
|
@ -75,8 +75,10 @@ addEntry() {
|
||||
|
||||
copyToKernelsDir "$path/kernel"; kernel=$result
|
||||
copyToKernelsDir "$path/initrd"; initrd=$result
|
||||
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
|
||||
copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
|
||||
if [ -n "@kernelDTB@" ]; then
|
||||
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
|
||||
copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
|
||||
fi
|
||||
|
||||
timestampEpoch=$(stat -L -c '%Z' $path)
|
||||
|
||||
@ -93,7 +95,9 @@ addEntry() {
|
||||
fi
|
||||
echo " LINUX ../nixos/$(basename $kernel)"
|
||||
echo " INITRD ../nixos/$(basename $initrd)"
|
||||
echo " FDTDIR ../nixos/$(basename $dtbs)"
|
||||
if [ -n "@kernelDTB@" ]; then
|
||||
echo " FDTDIR ../nixos/$(basename $dtbs)"
|
||||
fi
|
||||
echo " APPEND systemConfig=$path init=$path/init $extraParams"
|
||||
}
|
||||
|
||||
@ -105,20 +109,24 @@ cat > $tmpFile <<EOF
|
||||
# Change this to e.g. nixos-42 to temporarily boot to an older configuration.
|
||||
DEFAULT nixos-default
|
||||
|
||||
MENU TITLE ------------------------------------------------------------
|
||||
TIMEOUT $timeout
|
||||
$(addEntry $default default)
|
||||
EOF
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
|
@ -338,6 +338,7 @@ with stdenv.lib;
|
||||
X86_MCE y
|
||||
|
||||
# Linux containers.
|
||||
NAMESPACES? y # Required by 'unshare' used by 'nixos-install'
|
||||
RT_GROUP_SCHED? y
|
||||
CGROUP_DEVICE? y
|
||||
${if versionAtLeast version "3.6" then ''
|
||||
|
@ -7,7 +7,7 @@ let
|
||||
in import ./generic.nix (args // rec {
|
||||
version = "3.18.y-${rev}";
|
||||
|
||||
modDirVersion = "3.18.7-v7";
|
||||
modDirVersion = "3.18.7";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://api.github.com/repos/raspberrypi/linux/tarball/${rev}";
|
||||
|
Loading…
Reference in New Issue
Block a user