mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-01 15:11:25 +00:00
Use BusyBox in the initrd
Using BusyBox instead of Bash plus a bunch of other tools gives us a much more feature-full, yet smaller initrd. In particular, BusyBox contains networking commands such as ip and a DHCP client, useful for NFS boots. It's also much more convenient for rescue situations because the shell has builtin readline support and there are many more tools (including vi).
This commit is contained in:
parent
70089950d2
commit
9692495df0
@ -196,7 +196,6 @@
|
||||
./system/boot/luksroot.nix
|
||||
./system/boot/modprobe.nix
|
||||
./system/boot/stage-1.nix
|
||||
./system/boot/stage-1-extratools.nix
|
||||
./system/boot/stage-2.nix
|
||||
./system/etc/etc.nix
|
||||
./system/upstart-events/control-alt-delete.nix
|
||||
|
@ -1,54 +0,0 @@
|
||||
{ config, pkgs, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
staticBusybox = pkgs.busybox.override {
|
||||
enableStatic = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
boot.initrd.withExtraTools = mkOption {
|
||||
default = false;
|
||||
type = with types; bool;
|
||||
description = ''
|
||||
Have busybox utils in initrd, and an interactive bash.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
boot.initrd.extraUtilsCommands = mkIf config.boot.initrd.withExtraTools ''
|
||||
cp -pv ${pkgs.ncurses}/lib/libncurses*.so.* $out/lib
|
||||
cp -pv ${pkgs.readline}/lib/libreadline.so.* $out/lib
|
||||
cp -pv ${pkgs.readline}/lib/libhistory.so.* $out/lib
|
||||
rm $out/bin/bash
|
||||
cp -pv ${pkgs.bashInteractive}/bin/bash $out/bin
|
||||
|
||||
cp -pv ${staticBusybox}/bin/busybox $out/bin
|
||||
shopt -s nullglob
|
||||
for d in bin sbin; do
|
||||
pushd ${staticBusybox}/$d
|
||||
# busybox has these, but we'll put them later
|
||||
GLOBIGNORE=.:..:mke2fs:ip:modprobe
|
||||
for a in *; do
|
||||
if [ ! -e $out/bin/$a ]; then
|
||||
ln -sf busybox $out/bin/$a
|
||||
fi
|
||||
done
|
||||
popd
|
||||
done
|
||||
shopt -u nullglob
|
||||
unset GLOBIGNORE
|
||||
'';
|
||||
|
||||
boot.initrd.extraUtilsCommandsTest = mkIf config.boot.initrd.withExtraTools ''
|
||||
$out/bin/busybox
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
targetRoot=/mnt-root
|
||||
|
||||
export LD_LIBRARY_PATH=@extraUtils@/lib
|
||||
export PATH=@extraUtils@/bin
|
||||
export PATH=@extraUtils@/bin:@extraUtils@/sbin
|
||||
|
||||
|
||||
fail() {
|
||||
@ -50,7 +50,7 @@ EOF
|
||||
esac
|
||||
}
|
||||
|
||||
trap 'fail' ERR
|
||||
trap 'fail' 0
|
||||
|
||||
|
||||
# Print a greeting.
|
||||
@ -60,8 +60,9 @@ echo
|
||||
|
||||
|
||||
# Mount special file systems.
|
||||
mkdir -p /etc # to shut up mount
|
||||
echo -n > /etc/fstab # idem
|
||||
mkdir -p /etc
|
||||
touch /etc/fstab # to shut up mount
|
||||
touch /etc/mtab # to shut up mke2fs
|
||||
mkdir -p /proc
|
||||
mount -t proc none /proc
|
||||
mkdir -p /sys
|
||||
@ -120,6 +121,8 @@ done
|
||||
|
||||
|
||||
# Load the required kernel modules.
|
||||
mkdir -p /lib
|
||||
ln -s @modulesClosure@/lib/modules /lib/modules
|
||||
echo @extraUtils@/bin/modprobe > /proc/sys/kernel/modprobe
|
||||
for i in @kernelModules@; do
|
||||
echo "loading module $(basename $i)..."
|
||||
@ -259,16 +262,12 @@ mountFS() {
|
||||
# Try to find and mount the root device.
|
||||
mkdir /mnt-root
|
||||
|
||||
mountPoints=(@mountPoints@)
|
||||
devices=(@devices@)
|
||||
fsTypes=(@fsTypes@)
|
||||
optionss=(@optionss@)
|
||||
exec 3< @fsInfo@
|
||||
|
||||
for ((n = 0; n < ${#mountPoints[*]}; n++)); do
|
||||
mountPoint=${mountPoints[$n]}
|
||||
device=${devices[$n]}
|
||||
fsType=${fsTypes[$n]}
|
||||
options=${optionss[$n]}
|
||||
while read -u 3 mountPoint; do
|
||||
read -u 3 device
|
||||
read -u 3 fsType
|
||||
read -u 3 options
|
||||
|
||||
# !!! Really quick hack to support bind mounts, i.e., where the
|
||||
# "device" should be taken relative to /mnt-root, not /. Assume
|
||||
@ -300,7 +299,7 @@ for ((n = 0; n < ${#mountPoints[*]}; n++)); do
|
||||
# that we don't properly recognise.
|
||||
if test -z "$pseudoDevice" -a ! -e $device; then
|
||||
echo -n "waiting for device $device to appear..."
|
||||
for ((try = 0; try < 20; try++)); do
|
||||
for try in $(seq 1 20); do
|
||||
sleep 1
|
||||
if test -e $device; then break; fi
|
||||
echo -n "."
|
||||
@ -326,7 +325,7 @@ udevadm control --exit || true
|
||||
|
||||
# Kill any remaining processes, just to be sure we're not taking any
|
||||
# with us into stage 2.
|
||||
kill -9 -- -1
|
||||
pkill -9 -v 1
|
||||
|
||||
|
||||
if test -n "$debug1mounts"; then fail; fi
|
||||
|
@ -129,7 +129,7 @@ let
|
||||
# work.
|
||||
extraUtils = pkgs.runCommand "extra-utils"
|
||||
{ buildInputs = [pkgs.nukeReferences];
|
||||
allowedReferences = [ "out" modulesClosure ]; # prevent accidents like glibc being included in the initrd
|
||||
allowedReferences = [ "out" ]; # prevent accidents like glibc being included in the initrd
|
||||
doublePatchelf = (pkgs.stdenv.system == "armv5tel-linux");
|
||||
}
|
||||
''
|
||||
@ -139,28 +139,21 @@ let
|
||||
# Copy what we need from Glibc.
|
||||
cp -pv ${pkgs.glibc}/lib/ld*.so.? $out/lib
|
||||
cp -pv ${pkgs.glibc}/lib/libc.so.* $out/lib
|
||||
cp -pv ${pkgs.glibc}/lib/libm.so.* $out/lib
|
||||
cp -pv ${pkgs.glibc}/lib/libpthread.so.* $out/lib
|
||||
cp -pv ${pkgs.glibc}/lib/librt.so.* $out/lib
|
||||
cp -pv ${pkgs.glibc}/lib/libdl.so.* $out/lib
|
||||
cp -pv ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib
|
||||
|
||||
# Copy BusyBox.
|
||||
cp -rvd ${pkgs.busybox}/{bin,sbin} $out/
|
||||
chmod -R u+w $out
|
||||
|
||||
# Copy some utillinux stuff.
|
||||
cp -v ${pkgs.utillinux}/bin/mount ${pkgs.utillinux}/bin/umount \
|
||||
${pkgs.utillinux}/sbin/fsck ${pkgs.utillinux}/sbin/switch_root \
|
||||
${pkgs.utillinux}/sbin/blkid ${pkgs.utillinux}/bin/setsid $out/bin
|
||||
cp -v ${pkgs.utillinux}/sbin/blkid $out/bin
|
||||
cp -pdv ${pkgs.utillinux}/lib/libblkid*.so.* $out/lib
|
||||
cp -pdv ${pkgs.utillinux}/lib/libuuid*.so.* $out/lib
|
||||
|
||||
# Copy some coreutils.
|
||||
cp -v ${pkgs.coreutils}/bin/basename $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/mkdir $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/mknod $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/chmod $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/cat $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/chroot $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/sleep $out/bin
|
||||
cp -v ${pkgs.coreutils}/bin/ln $out/bin
|
||||
|
||||
|
||||
# Copy dmsetup and lvm.
|
||||
cp -v ${pkgs.lvm2}/sbin/dmsetup $out/bin/dmsetup
|
||||
cp -v ${pkgs.lvm2}/sbin/lvm $out/bin/lvm
|
||||
@ -174,12 +167,8 @@ let
|
||||
cp -v ${pkgs.udev}/lib/udev/*_id $out/bin
|
||||
cp -pdv ${pkgs.udev}/lib/libudev.so.* $out/lib
|
||||
|
||||
# Copy bash.
|
||||
cp -v ${pkgs.bash}/bin/bash $out/bin
|
||||
ln -sv bash $out/bin/sh
|
||||
|
||||
# Copy modprobe.
|
||||
cp -v ${pkgs.module_init_tools}/sbin/modprobe $out/bin/modprobe.real
|
||||
cp -v ${pkgs.module_init_tools}/sbin/modprobe $out/bin/modprobe
|
||||
|
||||
# Maybe copy splashutils.
|
||||
${optionalString enableSplashScreen ''
|
||||
@ -188,6 +177,10 @@ let
|
||||
|
||||
${config.boot.initrd.extraUtilsCommands}
|
||||
|
||||
# Strip binaries further than normal.
|
||||
chmod -R u+w $out
|
||||
stripDirs "lib bin" "-s"
|
||||
|
||||
# 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
|
||||
|
||||
@ -201,27 +194,15 @@ let
|
||||
fi
|
||||
done
|
||||
|
||||
# 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
|
||||
|
||||
# Make sure that the patchelf'ed binaries still work.
|
||||
echo "testing patched programs..."
|
||||
$out/bin/bash --version | grep "bash, version"
|
||||
$out/bin/ash -c 'echo hello world' | grep "hello world"
|
||||
export LD_LIBRARY_PATH=$out/lib
|
||||
$out/bin/mount --version | grep "mount from"
|
||||
$out/bin/umount --version | grep "umount "
|
||||
$out/bin/mount --help 2>&1 | grep "BusyBox"
|
||||
$out/bin/udevadm --version
|
||||
$out/bin/blkid -v 2>&1 | tee -a $out/log | grep "blkid from util-linux"
|
||||
$out/bin/dmsetup --version 2>&1 | tee -a $out/log | grep "version:"
|
||||
LVM_SYSTEM_DIR=$out $out/bin/lvm version 2>&1 | tee -a $out/log | grep "LVM"
|
||||
$out/bin/mdadm --version
|
||||
$out/bin/basename --version
|
||||
$out/bin/modprobe --version
|
||||
|
||||
${config.boot.initrd.extraUtilsCommandsTest}
|
||||
''; # */
|
||||
@ -291,25 +272,20 @@ let
|
||||
bootStage1 = pkgs.substituteAll {
|
||||
src = ./stage-1-init.sh;
|
||||
|
||||
shell = "${extraUtils}/bin/bash";
|
||||
shell = "${extraUtils}/bin/ash";
|
||||
|
||||
isExecutable = true;
|
||||
|
||||
inherit udevConf extraUtils;
|
||||
inherit udevConf extraUtils modulesClosure;
|
||||
|
||||
inherit (config.boot) resumeDevice devSize runSize;
|
||||
|
||||
inherit (config.boot.initrd) checkJournalingFS
|
||||
preLVMCommands postDeviceCommands postMountCommands kernelModules;
|
||||
|
||||
# !!! copy&pasted from upstart-jobs/filesystems.nix.
|
||||
mountPoints =
|
||||
if fileSystems == []
|
||||
then abort "You must specify the fileSystems option!"
|
||||
else map (fs: fs.mountPoint) fileSystems;
|
||||
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;
|
||||
fsInfo =
|
||||
let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType fs.options ];
|
||||
in pkgs.writeText "initrd-fsinfo" (concatStringsSep "\n" (concatMap f fileSystems));
|
||||
};
|
||||
|
||||
|
||||
|
@ -252,10 +252,6 @@ in
|
||||
''
|
||||
# We need mke2fs in the initrd.
|
||||
cp ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin
|
||||
|
||||
# And `ip' (which needs libresolv.so).
|
||||
cp ${pkgs.iproute}/sbin/ip $out/bin
|
||||
cp ${pkgs.glibc}/lib/libresolv.so.* $out/lib
|
||||
'';
|
||||
|
||||
boot.initrd.postDeviceCommands =
|
||||
|
Loading…
Reference in New Issue
Block a user