* Use normal, dynamically linked binaries for e2fsck, lvm etc. in the

initrd instead of a mix of dietlibc, klibc and static-glibc based
  binaries.  This works by copying what we need from Glibc into the
  initrd and using patchelf to set the ELF interpreter and RPATH
  correctly.  The resulting initrd is about 500 KB smaller, but more
  importantly, it's much easier to maintain - all those
  dietlibc/klibc/static-glibc builds frequently cause build problems.

svn path=/nixos/branches/fix-style/; revision=14178
This commit is contained in:
Nicolas Pierron 2009-02-22 16:08:13 +00:00
parent 6c703347a8
commit 38e8cf175f
2 changed files with 80 additions and 58 deletions

View File

@ -1,7 +1,9 @@
#! @staticShell@ #! @shell@
targetRoot=/mnt/root targetRoot=/mnt/root
export LD_LIBRARY_PATH=@extraUtils@/lib
errorDialog() { errorDialog() {
timeout=15 timeout=15
@ -14,13 +16,13 @@ errorDialog() {
read -t $timeout reply read -t $timeout reply
case $reply in case $reply in
f) f)
exec @staticShell@;; exec @shell@;;
i) i)
echo echo
echo "Quit interactive shell with exit status of" echo "Quit interactive shell with exit status of"
echo " 0 : to continue" echo " 0 : to continue"
echo " non-zero : to get this dialog again" echo " non-zero : to get this dialog again"
@staticShell@ || fail @shell@ || fail
;; ;;
*) *)
echo continuing ignoring error;; echo continuing ignoring error;;
@ -299,7 +301,6 @@ umount /proc
exec run-init "$targetRoot" "$stage2Init" exec run-init "$targetRoot" "$stage2Init"
echo echo
echo $1 failed running "$stage2Init" echo "$1: failed running $stage2Init"
echo "It's your last chance to fix things manually without rebooting" echo "Dropping into a root shell..."
echo "finally switching to interactive shell pid 1" export $stage2Init; exec @shell@
export $stage2Init; exec @staticShell@

View File

@ -13,26 +13,6 @@ in
rec { rec {
pkgsDiet = import "${pkgs.path}/top-level/all-packages.nix" {
system = pkgs.stdenv.system;
bootStdenv = pkgs.useDietLibC pkgs.stdenv;
};
pkgsKlibc = import "${pkgs.path}/top-level/all-packages.nix" {
system = pkgs.stdenv.system;
bootStdenv = pkgs.useKlibc pkgs.stdenv pkgs.klibc;
};
pkgsStatic = import "${pkgs.path}/top-level/all-packages.nix" {
system = pkgs.stdenv.system;
bootStdenv = pkgs.makeStaticBinaries pkgs.stdenv;
};
stdenvLinuxStuff = import "${pkgs.path}/stdenv/linux" {
system = pkgs.stdenv.system;
allPackages = import "${pkgs.path}/top-level/all-packages.nix";
};
# Determine the set of modules that we need to mount the root FS. # Determine the set of modules that we need to mount the root FS.
modulesClosure = pkgs.makeModulesClosure { modulesClosure = pkgs.makeModulesClosure {
@ -44,41 +24,82 @@ rec {
}; };
udev = pkgsKlibc.udev; # 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,
# Some additional utilities needed in stage 1, notably mount. We # we just copy what we need from Glibc and use patchelf to make it
# don't want to bring in all of util-linux, so we just copy what we # work.
# need.
extraUtils = pkgs.runCommand "extra-utils" extraUtils = pkgs.runCommand "extra-utils"
{ buildInputs = [pkgs.nukeReferences]; { buildInputs = [pkgs.nukeReferences];
inherit (pkgsStatic) utillinux; devicemapper = if config.boot.initrd.lvm then pkgs.devicemapper else null;
inherit udev; lvm2 = if config.boot.initrd.lvm then pkgs.lvm2 else null;
e2fsprogs = pkgsDiet.e2fsprogs; allowedReferences = ["out"]; # prevent accidents like glibc being included in the initrd
devicemapper =
if config.boot.initrd.lvm
then assert pkgs.devicemapper.enableStatic; pkgs.devicemapper
else null;
lvm2 =
if config.boot.initrd.lvm
then assert pkgs.lvm2.enableStatic; pkgs.lvm2
else null;
allowedReferences = []; # prevent accidents like glibc being included in the initrd
} }
'' ''
ensureDir $out/bin ensureDir $out/bin
if test -n "$devicemapper"; then ensureDir $out/lib
cp $devicemapper/sbin/dmsetup.static $out/bin/dmsetup
cp $lvm2/sbin/lvm.static $out/bin/lvm # Copy what we need from Glibc.
fi cp -p ${pkgs.glibc}/lib/ld-linux*.so.2 $out/lib
cp $utillinux/bin/mount $utillinux/bin/umount $utillinux/sbin/pivot_root $out/bin cp -p ${pkgs.glibc}/lib/libc.so.* $out/lib
cp -pd $e2fsprogs/sbin/fsck $e2fsprogs/sbin/e2fsck $e2fsprogs/sbin/tune2fs $out/bin 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
# Copy some utillinux stuff.
cp ${pkgs.utillinux}/bin/mount ${pkgs.utillinux}/bin/umount ${pkgs.utillinux}/sbin/pivot_root $out/bin
# Copy e2fsck and friends.
cp ${pkgs.e2fsprogs}/sbin/e2fsck $out/bin
cp ${pkgs.e2fsprogs}/sbin/tune2fs $out/bin
cp ${pkgs.e2fsprogs}/sbin/fsck $out/bin
ln -s e2fsck $out/bin/fsck.ext2 ln -s e2fsck $out/bin/fsck.ext2
ln -s e2fsck $out/bin/fsck.ext3 ln -s e2fsck $out/bin/fsck.ext3
ln -s e2fsck $out/bin/fsck.ext4 ln -s e2fsck $out/bin/fsck.ext4
cp $udev/sbin/udevd $udev/sbin/udevadm $out/bin
cp $udev/lib/udev/*_id $out/bin cp -pd ${pkgs.e2fsprogs}/lib/lib*.so.* $out/lib
for i in $out/bin/*; do if ! test -L $i; then nuke-refs $i; fi; done
# Copy devicemapper and lvm, if we need it.
if test -n "$devicemapper"; then
cp $devicemapper/sbin/dmsetup $out/bin/dmsetup
cp $devicemapper/lib/libdevmapper.so.*.* $out/lib
cp $lvm2/sbin/lvm $out/bin/lvm
fi
# Copy udev.
cp ${pkgs.udev}/sbin/udevd ${pkgs.udev}/sbin/udevadm $out/bin
cp ${pkgs.udev}/lib/udev/*_id $out/bin
cp ${pkgs.udev}/lib/libvolume_id.so.* $out/lib
# Copy bash.
cp ${pkgs.bash}/bin/bash $out/bin
ln -s bash $out/bin/sh
# 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..."
patchelf --set-interpreter $out/lib/ld-linux*.so.2 --set-rpath $out/lib $i || true
fi
done
# 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
$out/bin/vol_id 2>&1 | grep "no device"
if test -n "$devicemapper"; then
$out/bin/dmsetup --version | grep "version:"
LVM_SYSTEM_DIR=$out $out/bin/lvm 2>&1 | grep "LVM"
fi
''; # */ ''; # */
@ -94,7 +115,7 @@ rec {
name = "udev-rules"; name = "udev-rules";
buildCommand = '' buildCommand = ''
ensureDir $out ensureDir $out
cp ${udev}/*/udev/rules.d/60-persistent-storage.rules $out/ cp ${pkgs.udev}/*/udev/rules.d/60-persistent-storage.rules $out/
substituteInPlace $out/60-persistent-storage.rules \ substituteInPlace $out/60-persistent-storage.rules \
--replace ata_id ${extraUtils}/bin/ata_id \ --replace ata_id ${extraUtils}/bin/ata_id \
--replace usb_id ${extraUtils}/bin/usb_id \ --replace usb_id ${extraUtils}/bin/usb_id \
@ -117,11 +138,11 @@ rec {
bootStage1 = pkgs.substituteAll { bootStage1 = pkgs.substituteAll {
src = ./boot-stage-1-init.sh; src = ./boot-stage-1-init.sh;
shell = "${extraUtils}/bin/bash";
isExecutable = true; isExecutable = true;
staticShell = stdenvLinuxStuff.bootstrapTools.bash; inherit modulesClosure udevConf extraUtils;
inherit modulesClosure udevConf;
inherit (config.boot) isLiveCD resumeDevice; inherit (config.boot) isLiveCD resumeDevice;