2009-05-27 08:14:06 +00:00
|
|
|
# This module builds the initial ramdisk, which contains an init
|
|
|
|
# script that performs the first stage of booting the system: it loads
|
|
|
|
# the modules necessary to mount the root file system, then calls the
|
|
|
|
# init in the root file system to start the second boot stage.
|
2006-11-02 22:48:01 +00:00
|
|
|
|
2009-12-15 16:38:20 +00:00
|
|
|
{ config, pkgs, ... }:
|
2008-11-23 01:29:20 +00:00
|
|
|
|
|
|
|
let
|
2009-05-27 09:46:50 +00:00
|
|
|
|
2009-06-11 16:04:03 +00:00
|
|
|
inherit (pkgs.lib) mkOption types;
|
2009-05-27 09:46:50 +00:00
|
|
|
|
|
|
|
options = {
|
|
|
|
|
|
|
|
boot.resumeDevice = mkOption {
|
|
|
|
default = "";
|
|
|
|
example = "0:0";
|
|
|
|
description = "
|
|
|
|
Device for manual resume attempt during boot. Looks like
|
|
|
|
major:minor. ls -l /dev/SWAP_PARTION shows them.
|
|
|
|
";
|
|
|
|
};
|
|
|
|
|
|
|
|
boot.initrd.enableSplashScreen = mkOption {
|
|
|
|
default = true;
|
|
|
|
description = "
|
|
|
|
Whether to show a nice splash screen while booting.
|
|
|
|
";
|
|
|
|
};
|
2009-06-11 16:04:03 +00:00
|
|
|
|
2009-06-15 16:47:37 +00:00
|
|
|
boot.initrd.checkJournalingFS = mkOption {
|
|
|
|
default = true;
|
|
|
|
type = types.bool;
|
|
|
|
description = ''
|
|
|
|
Whether to run fsck on journaling filesystems such as ext3.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-06-18 16:47:00 +00:00
|
|
|
boot.initrd.postDeviceCommands = mkOption {
|
|
|
|
default = "";
|
|
|
|
merge = pkgs.lib.mergeStringOption;
|
|
|
|
description = ''
|
|
|
|
Shell commands to be executed immediately after stage 1 of the
|
|
|
|
boot has loaded kernel modules and created device nodes in
|
|
|
|
/dev.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-06-18 16:03:18 +00:00
|
|
|
boot.initrd.postMountCommands = mkOption {
|
|
|
|
default = "";
|
|
|
|
merge = pkgs.lib.mergeStringOption;
|
|
|
|
description = ''
|
|
|
|
Shell commands to be executed immediately after the stage 1
|
2009-06-18 16:47:00 +00:00
|
|
|
filesystems have been mounted.
|
2009-06-18 16:03:18 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-06-19 15:19:56 +00:00
|
|
|
boot.initrd.extraUtilsCommands = mkOption {
|
2009-12-15 16:38:20 +00:00
|
|
|
internal = true;
|
2009-06-19 15:19:56 +00:00
|
|
|
default = "";
|
|
|
|
merge = pkgs.lib.mergeStringOption;
|
|
|
|
description = ''
|
|
|
|
Shell commands to be executed in the builder of the
|
|
|
|
extra-utils derivation. This can be used to provide
|
|
|
|
additional utilities in the initial ramdisk.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-06-11 16:04:03 +00:00
|
|
|
fileSystems = mkOption {
|
|
|
|
options.neededForBoot = mkOption {
|
|
|
|
default = false;
|
2009-06-14 11:08:44 +00:00
|
|
|
type = types.bool;
|
2009-06-11 16:04:03 +00:00
|
|
|
description = "
|
|
|
|
Mount this file system to boot on NixOS.
|
|
|
|
";
|
|
|
|
};
|
|
|
|
};
|
2009-05-27 09:46:50 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-11-23 01:29:20 +00:00
|
|
|
kernelPackages = config.boot.kernelPackages;
|
|
|
|
modulesTree = config.system.modulesTree;
|
2008-08-08 17:34:30 +00:00
|
|
|
|
2006-11-12 18:48:47 +00:00
|
|
|
|
2008-08-08 17:34:30 +00:00
|
|
|
# Determine the set of modules that we need to mount the root FS.
|
|
|
|
modulesClosure = pkgs.makeModulesClosure {
|
2009-12-15 16:38:20 +00:00
|
|
|
rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules;
|
2008-08-08 17:34:30 +00:00
|
|
|
kernel = modulesTree;
|
2009-12-15 16:38:20 +00:00
|
|
|
allowMissing = true;
|
2008-08-08 17:34:30 +00:00
|
|
|
};
|
2008-01-24 16:56:09 +00:00
|
|
|
|
2006-11-13 11:41:27 +00:00
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
# Some additional utilities needed in stage 1, like mount, lvm, fsck
|
|
|
|
# etc. We don't want to bring in all of those packages, so we just
|
|
|
|
# copy what we need. Instead of using statically linked binaries,
|
|
|
|
# we just copy what we need from Glibc and use patchelf to make it
|
|
|
|
# work.
|
2008-08-08 17:34:30 +00:00
|
|
|
extraUtils = pkgs.runCommand "extra-utils"
|
|
|
|
{ buildInputs = [pkgs.nukeReferences];
|
2009-12-15 16:38:20 +00:00
|
|
|
allowedReferences = [ "out" modulesClosure ]; # prevent accidents like glibc being included in the initrd
|
2009-09-23 20:50:48 +00:00
|
|
|
doublePatchelf = (pkgs.stdenv.system == "armv5tel-linux");
|
2008-08-08 17:34:30 +00:00
|
|
|
}
|
|
|
|
''
|
|
|
|
ensureDir $out/bin
|
2009-02-22 16:08:13 +00:00
|
|
|
ensureDir $out/lib
|
|
|
|
|
|
|
|
# Copy what we need from Glibc.
|
2009-09-23 20:50:48 +00:00
|
|
|
cp -p ${pkgs.glibc}/lib/ld-linux*.so.? $out/lib
|
2009-02-22 16:08:13 +00:00
|
|
|
cp -p ${pkgs.glibc}/lib/libc.so.* $out/lib
|
|
|
|
cp -p ${pkgs.glibc}/lib/libpthread.so.* $out/lib
|
|
|
|
cp -p ${pkgs.glibc}/lib/librt.so.* $out/lib
|
|
|
|
cp -p ${pkgs.glibc}/lib/libdl.so.* $out/lib
|
2009-09-25 12:34:09 +00:00
|
|
|
cp -p ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib
|
2009-02-22 16:08:13 +00:00
|
|
|
|
|
|
|
# Copy some utillinux stuff.
|
2009-08-11 21:12:37 +00:00
|
|
|
cp ${pkgs.utillinux}/bin/mount ${pkgs.utillinux}/bin/umount \
|
|
|
|
${pkgs.utillinux}/sbin/fsck ${pkgs.utillinux}/sbin/pivot_root \
|
|
|
|
${pkgs.utillinux}/sbin/blkid $out/bin
|
|
|
|
cp -pd ${pkgs.utillinux}/lib/libblkid*.so.* $out/lib
|
|
|
|
cp -pd ${pkgs.utillinux}/lib/libuuid*.so.* $out/lib
|
2009-02-22 16:08:13 +00:00
|
|
|
|
2009-06-10 15:02:39 +00:00
|
|
|
# Copy some coreutils.
|
|
|
|
cp ${pkgs.coreutils}/bin/basename $out/bin
|
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
# Copy e2fsck and friends.
|
|
|
|
cp ${pkgs.e2fsprogs}/sbin/e2fsck $out/bin
|
|
|
|
cp ${pkgs.e2fsprogs}/sbin/tune2fs $out/bin
|
2009-03-29 10:59:13 +00:00
|
|
|
cp ${pkgs.reiserfsprogs}/sbin/reiserfsck $out/bin
|
2009-02-22 16:08:09 +00:00
|
|
|
ln -s e2fsck $out/bin/fsck.ext2
|
|
|
|
ln -s e2fsck $out/bin/fsck.ext3
|
|
|
|
ln -s e2fsck $out/bin/fsck.ext4
|
2009-03-29 10:59:13 +00:00
|
|
|
ln -s reiserfsck $out/bin/fsck.reiserfs
|
2009-02-22 16:08:13 +00:00
|
|
|
|
|
|
|
cp -pd ${pkgs.e2fsprogs}/lib/lib*.so.* $out/lib
|
|
|
|
|
2010-01-10 19:00:29 +00:00
|
|
|
# Copy dmsetup and lvm.
|
2010-01-10 16:32:30 +00:00
|
|
|
cp ${pkgs.lvm2}/sbin/dmsetup $out/bin/dmsetup
|
|
|
|
cp ${pkgs.lvm2}/sbin/lvm $out/bin/lvm
|
|
|
|
cp ${pkgs.lvm2}/lib/libdevmapper.so.*.* $out/lib
|
2009-02-22 16:08:13 +00:00
|
|
|
|
2009-03-31 09:27:11 +00:00
|
|
|
# Add RAID mdadm tool.
|
2009-03-29 10:59:13 +00:00
|
|
|
cp ${pkgs.mdadm}/sbin/mdadm $out/bin/mdadm
|
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
# Copy udev.
|
|
|
|
cp ${pkgs.udev}/sbin/udevd ${pkgs.udev}/sbin/udevadm $out/bin
|
2009-08-11 21:12:37 +00:00
|
|
|
cp ${pkgs.udev}/libexec/*_id $out/bin
|
2009-02-22 16:08:13 +00:00
|
|
|
|
|
|
|
# Copy bash.
|
|
|
|
cp ${pkgs.bash}/bin/bash $out/bin
|
|
|
|
ln -s bash $out/bin/sh
|
|
|
|
|
2009-12-15 16:38:20 +00:00
|
|
|
# Copy modprobe.
|
|
|
|
cp ${pkgs.module_init_tools}/sbin/modprobe $out/bin/modprobe.real
|
|
|
|
|
2009-06-19 15:19:56 +00:00
|
|
|
${config.boot.initrd.extraUtilsCommands}
|
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
# Run patchelf to make the programs refer to the copied libraries.
|
|
|
|
for i in $out/bin/* $out/lib/*; do if ! test -L $i; then nuke-refs $i; fi; done
|
|
|
|
|
|
|
|
for i in $out/bin/*; do
|
|
|
|
if ! test -L $i; then
|
|
|
|
echo "patching $i..."
|
2009-09-23 20:50:48 +00:00
|
|
|
patchelf --set-interpreter $out/lib/ld-linux*.so.? --set-rpath $out/lib $i || true
|
2009-12-15 16:38:20 +00:00
|
|
|
if [ -n "$doublePatchelf" ]; then
|
2009-09-23 20:50:48 +00:00
|
|
|
patchelf --set-interpreter $out/lib/ld-linux*.so.? --set-rpath $out/lib $i || true
|
|
|
|
fi
|
2009-02-22 16:08:13 +00:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
2009-12-15 16:38:20 +00:00
|
|
|
# Make the modprobe wrapper that sets $MODULE_DIR.
|
|
|
|
cat > $out/bin/modprobe <<EOF
|
|
|
|
#! $out/bin/bash
|
|
|
|
export MODULE_DIR=${modulesClosure}/lib/modules
|
|
|
|
exec $out/bin/modprobe.real "\$@"
|
|
|
|
EOF
|
|
|
|
chmod u+x $out/bin/modprobe
|
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
# Make sure that the patchelf'ed binaries still work.
|
|
|
|
echo "testing patched programs..."
|
|
|
|
$out/bin/bash --version
|
|
|
|
export LD_LIBRARY_PATH=$out/lib
|
|
|
|
$out/bin/mount --version
|
|
|
|
$out/bin/umount --version
|
|
|
|
$out/bin/e2fsck -V
|
|
|
|
$out/bin/tune2fs 2> /dev/null | grep "tune2fs "
|
|
|
|
$out/bin/fsck -N
|
|
|
|
$out/bin/udevadm --version
|
2009-08-11 21:12:37 +00:00
|
|
|
$out/bin/blkid -v 2>&1 | grep "blkid from util-linux-ng"
|
2010-01-10 16:32:30 +00:00
|
|
|
$out/bin/dmsetup --version 2>&1 | grep "version:"
|
|
|
|
LVM_SYSTEM_DIR=$out $out/bin/lvm 2>&1 | grep "LVM"
|
2009-03-31 09:27:11 +00:00
|
|
|
$out/bin/reiserfsck -V
|
|
|
|
$out/bin/mdadm --version
|
2009-06-10 15:02:39 +00:00
|
|
|
$out/bin/basename --version
|
2009-12-15 16:38:20 +00:00
|
|
|
$out/bin/modprobe --version
|
2008-08-08 17:34:30 +00:00
|
|
|
''; # */
|
|
|
|
|
2006-11-02 22:48:01 +00:00
|
|
|
|
2008-08-08 17:34:30 +00:00
|
|
|
# The initrd only has to mount / or any FS marked as necessary for
|
|
|
|
# booting (such as the FS containing /nix/store, or an FS needed for
|
|
|
|
# mounting /, like / on a loopback).
|
|
|
|
fileSystems = pkgs.lib.filter
|
2009-06-11 16:04:03 +00:00
|
|
|
(fs: fs.mountPoint == "/" || fs.neededForBoot)
|
2008-08-08 17:34:30 +00:00
|
|
|
config.fileSystems;
|
2007-02-06 16:53:36 +00:00
|
|
|
|
2008-08-08 22:44:45 +00:00
|
|
|
|
|
|
|
udevRules = pkgs.stdenv.mkDerivation {
|
|
|
|
name = "udev-rules";
|
|
|
|
buildCommand = ''
|
|
|
|
ensureDir $out
|
2009-08-19 16:48:28 +00:00
|
|
|
|
|
|
|
cp ${pkgs.udev}/libexec/rules.d/60-cdrom_id.rules $out/
|
2009-08-11 21:12:37 +00:00
|
|
|
cp ${pkgs.udev}/libexec/rules.d/60-persistent-storage.rules $out/
|
2009-12-15 16:38:20 +00:00
|
|
|
cp ${pkgs.udev}/libexec/rules.d/80-drivers.rules $out/
|
2010-01-10 19:00:29 +00:00
|
|
|
cp ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
|
2009-08-19 16:48:28 +00:00
|
|
|
|
|
|
|
for i in $out/*.rules; do
|
|
|
|
substituteInPlace $i \
|
|
|
|
--replace ata_id ${extraUtils}/bin/ata_id \
|
|
|
|
--replace usb_id ${extraUtils}/bin/usb_id \
|
|
|
|
--replace scsi_id ${extraUtils}/bin/scsi_id \
|
|
|
|
--replace path_id ${extraUtils}/bin/path_id \
|
|
|
|
--replace vol_id ${extraUtils}/bin/vol_id \
|
|
|
|
--replace cdrom_id ${extraUtils}/bin/cdrom_id \
|
2009-12-15 16:38:20 +00:00
|
|
|
--replace /sbin/blkid ${extraUtils}/bin/blkid \
|
2010-01-10 19:00:29 +00:00
|
|
|
--replace /sbin/modprobe ${extraUtils}/bin/modprobe \
|
|
|
|
--replace '$env{DM_SBIN_PATH}/blkid' ${extraUtils}/bin/blkid \
|
|
|
|
--replace 'ENV{DM_SBIN_PATH}="/sbin"' 'ENV{DM_SBIN_PATH}="${extraUtils}/bin"'
|
2009-08-19 16:48:28 +00:00
|
|
|
done
|
|
|
|
|
2009-08-19 17:24:33 +00:00
|
|
|
# Remove rule preventing creation of a by-label symlink
|
|
|
|
# for a CD-ROM if disk removal will not be properly reported.
|
|
|
|
# Such a link can get obsolete in a running system, but
|
|
|
|
# during boot stage 1 it is unlikely. We need this change
|
|
|
|
# to be able to boot on a wider choice of CD drives.
|
2009-05-18 11:59:40 +00:00
|
|
|
sed -e '/^ENV[{]DEVTYPE[}]=="disk", .*GOTO/d' -i $out/60-persistent-storage.rules
|
2008-08-08 22:44:45 +00:00
|
|
|
''; # */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
# The udev configuration file for in the initrd.
|
|
|
|
udevConf = pkgs.writeText "udev-initrd.conf" ''
|
|
|
|
udev_rules="${udevRules}"
|
|
|
|
#udev_log="debug"
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
2008-08-08 17:34:30 +00:00
|
|
|
# The init script of boot stage 1 (loading kernel modules for
|
|
|
|
# mounting the root FS).
|
|
|
|
bootStage1 = pkgs.substituteAll {
|
2009-05-25 14:19:33 +00:00
|
|
|
src = ./stage-1-init.sh;
|
2007-02-06 16:53:36 +00:00
|
|
|
|
2009-02-22 16:08:13 +00:00
|
|
|
shell = "${extraUtils}/bin/bash";
|
|
|
|
|
2008-08-08 17:34:30 +00:00
|
|
|
isExecutable = true;
|
2007-02-06 16:53:36 +00:00
|
|
|
|
2009-12-15 16:38:20 +00:00
|
|
|
klibc = pkgs.klibcShrunk;
|
|
|
|
|
|
|
|
inherit udevConf extraUtils;
|
|
|
|
|
2010-01-09 15:13:06 +00:00
|
|
|
inherit (config.boot) resumeDevice;
|
2007-02-06 16:53:36 +00:00
|
|
|
|
2009-06-18 16:47:00 +00:00
|
|
|
inherit (config.boot.initrd) checkJournalingFS
|
2009-12-15 16:38:20 +00:00
|
|
|
postDeviceCommands postMountCommands kernelModules;
|
2009-06-15 16:47:37 +00:00
|
|
|
|
2008-08-08 17:34:30 +00:00
|
|
|
# !!! copy&pasted from upstart-jobs/filesystems.nix.
|
|
|
|
mountPoints =
|
2009-03-09 19:18:27 +00:00
|
|
|
if fileSystems == null
|
2008-08-08 17:34:30 +00:00
|
|
|
then abort "You must specify the fileSystems option!"
|
|
|
|
else map (fs: fs.mountPoint) fileSystems;
|
2009-06-14 11:08:44 +00:00
|
|
|
devices = map (fs: if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fileSystems;
|
|
|
|
fsTypes = map (fs: fs.fsType) fileSystems;
|
|
|
|
optionss = map (fs: fs.options) fileSystems;
|
2008-08-08 17:34:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
# The closure of the init script of boot stage 1 is what we put in
|
|
|
|
# the initial RAM disk.
|
|
|
|
initialRamdisk = pkgs.makeInitrd {
|
|
|
|
contents = [
|
|
|
|
{ object = bootStage1;
|
|
|
|
symlink = "/init";
|
|
|
|
}
|
|
|
|
] ++
|
|
|
|
pkgs.lib.optionals
|
|
|
|
(config.boot.initrd.enableSplashScreen && kernelPackages.splashutils != null)
|
|
|
|
[
|
|
|
|
{ object = pkgs.runCommand "splashutils" {allowedReferences = []; buildInputs = [pkgs.nukeReferences];} ''
|
|
|
|
ensureDir $out/bin
|
|
|
|
cp ${kernelPackages.splashutils}/${kernelPackages.splashutils.helperName} $out/bin/splash_helper
|
|
|
|
nuke-refs $out/bin/*
|
|
|
|
'';
|
|
|
|
suffix = "/bin/splash_helper";
|
|
|
|
symlink = "/${kernelPackages.splashutils.helperName}";
|
|
|
|
} # */
|
2009-05-29 14:46:27 +00:00
|
|
|
{ object = import ../../../lib/unpack-theme.nix {
|
2008-08-08 17:34:30 +00:00
|
|
|
inherit (pkgs) stdenv;
|
|
|
|
theme = config.services.ttyBackgrounds.defaultTheme;
|
|
|
|
};
|
|
|
|
symlink = "/etc/splash";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
2008-08-08 15:49:57 +00:00
|
|
|
|
2009-05-27 08:14:06 +00:00
|
|
|
in {
|
|
|
|
|
2009-05-27 09:46:50 +00:00
|
|
|
require = [options];
|
|
|
|
|
2009-05-27 08:14:06 +00:00
|
|
|
system.build.bootStage1 = bootStage1;
|
|
|
|
system.build.initialRamdisk = initialRamdisk;
|
|
|
|
|
2006-11-02 22:48:01 +00:00
|
|
|
}
|