From 3ee0b9bb74b0331e0aae0bb452074ef14967393f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 17 Mar 2008 10:40:47 +0000 Subject: [PATCH] * makeInitrd, makeModulesClosure: moved from NixOS. * Use sh from klibc in the initrd. svn path=/nixpkgs/trunk/; revision=11154 --- pkgs/build-support/kernel/make-initrd.nix | 31 +++++++++ pkgs/build-support/kernel/make-initrd.sh | 39 +++++++++++ pkgs/build-support/kernel/modules-closure.nix | 13 ++++ pkgs/build-support/kernel/modules-closure.sh | 36 ++++++++++ pkgs/build-support/kernel/paths-from-graph.pl | 68 +++++++++++++++++++ pkgs/build-support/vm/vm.nix | 56 ++++----------- pkgs/top-level/all-packages.nix | 8 +++ 7 files changed, 210 insertions(+), 41 deletions(-) create mode 100644 pkgs/build-support/kernel/make-initrd.nix create mode 100644 pkgs/build-support/kernel/make-initrd.sh create mode 100644 pkgs/build-support/kernel/modules-closure.nix create mode 100644 pkgs/build-support/kernel/modules-closure.sh create mode 100644 pkgs/build-support/kernel/paths-from-graph.pl diff --git a/pkgs/build-support/kernel/make-initrd.nix b/pkgs/build-support/kernel/make-initrd.nix new file mode 100644 index 000000000000..b62ed9840456 --- /dev/null +++ b/pkgs/build-support/kernel/make-initrd.nix @@ -0,0 +1,31 @@ +# Create an initial ramdisk containing the closure of the specified +# file system objects. An initial ramdisk is used during the initial +# stages of booting a Linux system. It is loaded by the boot loader +# along with the kernel image. It's supposed to contain everything +# (such as kernel modules) necessary to allow us to mount the root +# file system. Once the root file system is mounted, the `real' boot +# script can be called. +# +# An initrd is really just a gzipped cpio archive. +# +# Symlinks are created for each top-level file system object. E.g., +# `contents = {object = ...; symlink = /init;}' is a typical +# argument. + +{stdenv, perl, cpio, contents}: + +stdenv.mkDerivation { + name = "initrd"; + builder = ./make-initrd.sh; + buildInputs = [perl cpio]; + + # !!! should use XML. + objects = map (x: x.object) contents; + symlinks = map (x: x.symlink) contents; + suffices = map (x: if x ? suffix then x.suffix else "none") contents; + + # For obtaining the closure of `contents'. + exportReferencesGraph = + map (x: [("closure-" + baseNameOf x.symlink) x.object]) contents; + pathsFromGraph = ./paths-from-graph.pl; +} diff --git a/pkgs/build-support/kernel/make-initrd.sh b/pkgs/build-support/kernel/make-initrd.sh new file mode 100644 index 000000000000..d930e51a03f9 --- /dev/null +++ b/pkgs/build-support/kernel/make-initrd.sh @@ -0,0 +1,39 @@ +source $stdenv/setup + +set -o pipefail + +objects=($objects) +symlinks=($symlinks) +suffices=($suffices) + +mkdir root + +# Needed for splash_helper, which gets run before init. +mkdir root/dev +mkdir root/sys +mkdir root/proc + + +for ((n = 0; n < ${#objects[*]}; n++)); do + object=${objects[$n]} + symlink=${symlinks[$n]} + suffix=${suffices[$n]} + if test "$suffix" = none; then suffix=; fi + + mkdir -p $(dirname root/$symlink) + ln -s $object$suffix root/$symlink +done + + +# Get the paths in the closure of `object'. +storePaths=$(perl $pathsFromGraph closure-*) + + +# Paths in cpio archives *must* be relative, otherwise the kernel +# won't unpack 'em. +(cd root && cp -prd --parents $storePaths .) + + +# Put the closure in a gzipped cpio archive. +ensureDir $out +(cd root && find * -print0 | cpio -ov -H newc --null | gzip -9 > $out/initrd) diff --git a/pkgs/build-support/kernel/modules-closure.nix b/pkgs/build-support/kernel/modules-closure.nix new file mode 100644 index 000000000000..86015a8b182c --- /dev/null +++ b/pkgs/build-support/kernel/modules-closure.nix @@ -0,0 +1,13 @@ +# Given a kernel build (with modules in $kernel/lib/modules/VERSION), +# produce a module tree in $out/lib/modules/VERSION that contains only +# the modules identified by `rootModules', plus their dependencies. +# Also generate an appropriate modules.dep. + +{stdenv, kernel, rootModules, module_init_tools}: + +stdenv.mkDerivation { + name = kernel.name + "-shrunk"; + builder = ./modules-closure.sh; + inherit kernel rootModules module_init_tools; + allowedReferences = ["out"]; +} diff --git a/pkgs/build-support/kernel/modules-closure.sh b/pkgs/build-support/kernel/modules-closure.sh new file mode 100644 index 000000000000..d16ff46ecb99 --- /dev/null +++ b/pkgs/build-support/kernel/modules-closure.sh @@ -0,0 +1,36 @@ +source $stdenv/setup + +set -o pipefail + +PATH=$module_init_tools/sbin:$PATH + +version=$(cd $kernel/lib/modules && ls -d *) + +echo "kernel version is $version" + +export MODULE_DIR=$kernel/lib/modules/ + +# Determine the dependencies of each root module. +closure= +for module in $rootModules; do + echo "root module: $module" + deps=$(modprobe --config /dev/null --set-version "$version" --show-depends "$module" \ + | sed 's/^insmod //') + #for i in $deps; do echo $i; done + closure="$closure $deps" +done + +echo "closure:" +ensureDir $out +for module in $closure; do + target=$(echo $module | sed "s^$kernel^$out^") + if test -e "$target"; then continue; fi + echo $module + mkdir -p $(dirname $target) + cp $module $target + grep "^$module" $kernel/lib/modules/$version/modules.dep \ + | sed "s^$kernel^$out^g" \ + >> $out/lib/modules/$version/modules.dep + echo $target >> $out/insmod-list +done + diff --git a/pkgs/build-support/kernel/paths-from-graph.pl b/pkgs/build-support/kernel/paths-from-graph.pl new file mode 100644 index 000000000000..43ce4e68db44 --- /dev/null +++ b/pkgs/build-support/kernel/paths-from-graph.pl @@ -0,0 +1,68 @@ +use strict; +use File::Basename; + +my %storePaths; +my %refs; + +foreach my $graph (@ARGV) { + open GRAPH, "<$graph" or die; + + while () { + chomp; + my $storePath = "$_"; + $storePaths{$storePath} = 1; + + my $deriver = ; chomp $deriver; + my $count = ; chomp $count; + + my @refs = (); + for (my $i = 0; $i < $count; ++$i) { + my $ref = ; chomp $ref; + push @refs, $ref; + } + $refs{$storePath} = \@refs; + + } + + close GRAPH; +} + + +if ($ENV{"printManifest"} eq "1") { + print "version {\n"; + print " ManifestVersion: 3\n"; + print "}\n"; + + foreach my $storePath (sort (keys %storePaths)) { + my $base = basename $storePath; + print "localPath {\n"; + print " StorePath: $storePath\n"; + print " CopyFrom: /tmp/inst-store/$base\n"; + print " References: "; + foreach my $ref (@{$refs{$storePath}}) { + print "$ref "; + } + print "\n"; + print "}\n"; + } +} + +elsif ($ENV{"printRegistration"} eq "1") { + # This is the format used by `nix-store --register-validity + # --hash-given' / `nix-store --load-db'. + foreach my $storePath (sort (keys %storePaths)) { + print "$storePath\n"; + print "0000000000000000000000000000000000000000000000000000000000000000\n"; # !!! fix + print "\n"; # don't care about preserving the deriver + print scalar(@{$refs{$storePath}}), "\n"; + foreach my $ref (@{$refs{$storePath}}) { + print "$ref\n"; + } + } +} + +else { + foreach my $storePath (sort (keys %storePaths)) { + print "$storePath\n"; + } +} diff --git a/pkgs/build-support/vm/vm.nix b/pkgs/build-support/vm/vm.nix index 02b022bc584b..24cfbbe4d0f0 100644 --- a/pkgs/build-support/vm/vm.nix +++ b/pkgs/build-support/vm/vm.nix @@ -1,40 +1,15 @@ -with import ../../nixpkgs {}; +with import ../../.. {}; rec { - stdenvLinuxStuff = import ../../nixpkgs/pkgs/stdenv/linux { - system = stdenv.system; - allPackages = import ../../nixpkgs/pkgs/top-level/all-packages.nix; - }; - - modulesClosure = import ../../nixos/helpers/modules-closure.nix { - inherit stdenv module_init_tools kernel; + modulesClosure = makeModulesClosure { + inherit kernel; #rootModules = ["cifs" "ne2k_pci" "nls_utf8" "ata_piix" "sd_mod"]; rootModules = ["cifs" "ne2k_pci" "nls_utf8" "ide_disk" "ide_generic"]; }; - klibcShrunk = stdenv.mkDerivation { - name = "${klibc.name}"; - buildCommand = '' - ensureDir $out/lib - cp -prd ${klibc}/lib/klibc/bin $out/ - cp -p ${klibc}/lib/*.so $out/lib/ - chmod +w $out/* - old=$(echo ${klibc}/lib/klibc-*.so) - new=$(echo $out/lib/klibc-*.so) - for i in $out/bin/*; do - echo $i - sed "s^$old^$new^" -i $i - # !!! use patchelf - #patchelf --set-rpath /foo/bar $i - done - ''; # */ - allowedReferences = ["out"]; - }; - - mountCifs = (makeStaticBinaries stdenv).mkDerivation { name = "mount.cifs"; src = fetchurl { @@ -54,7 +29,7 @@ rec { stage1Init = writeScript "vm-run-stage1" '' - #! ${stdenvLinuxStuff.bootstrapTools.bash} -e + #! ${klibcShrunk}/bin/sh.shared -e echo START export PATH=${klibcShrunk}/bin:${mountCifs}/bin @@ -66,8 +41,8 @@ rec { for o in $(cat /proc/cmdline); do case $o in - useTmpRoot=1) - useTmpRoot=1 + mountDisk=1) + mountDisk=1 ;; command=*) set -- $(IFS==; echo $o) @@ -106,7 +81,7 @@ rec { mkdir /fs - if test -n "$useTmpRoot"; then + if test -z "$mountDisk"; then mount -t tmpfs none /fs else mount -t ext2 /dev/hda /fs @@ -145,8 +120,7 @@ rec { ''; - initrd = import ../../nixos/boot/make-initrd.nix { - inherit stdenv perl cpio; + initrd = makeInitrd { contents = [ { object = stage1Init; symlink = "/init"; @@ -193,7 +167,7 @@ rec { -smb / -hda $diskImage \ -kernel ${kernel}/vmlinuz \ -initrd ${initrd}/initrd \ - -append "console=ttyS0 panic=1 command=${stage2Init} tmpDir=$TMPDIR out=$out useTmpRoot=$useTmpRoot" \ + -append "console=ttyS0 panic=1 command=${stage2Init} tmpDir=$TMPDIR out=$out mountDisk=$mountDisk" \ $QEMU_OPTS ''; @@ -248,8 +222,6 @@ rec { runInLinuxVM (stdenv.mkDerivation { inherit name postInstall rpms; - useTmpRoot = true; - preVM = '' mkdir $out diskImage=$out/image @@ -292,7 +264,7 @@ rec { size = 1024; name = "test"; fullName = "Test Image"; - rpms = import ../rpm/fedora-3-packages.nix {inherit fetchurl;}; + rpms = import ./rpm/fedora-3-packages.nix {inherit fetchurl;}; }; @@ -322,6 +294,8 @@ rec { buildRPM = runInLinuxVM (stdenv.mkDerivation { name = "rpm-test"; + mountDisk = true; + preVM = '' diskImage=$(pwd)/image qemu-img create -b ${test2}/image -f qcow $diskImage @@ -355,8 +329,6 @@ rec { debs = (lib.intersperse "|" debs); - useTmpRoot = true; - preVM = '' mkdir $out diskImage=$out/image @@ -447,6 +419,8 @@ rec { test6 = runInLinuxVM (stdenv.mkDerivation { name = "deb-compile"; + + mountDisk = true; preVM = '' diskImage=$(pwd)/image @@ -473,5 +447,5 @@ rec { debs = import ./deb/debian-4.0r3-etch-i386.nix {inherit fetchurl;}; }; - + } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 56716e52c03e..012ff82989cd 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -354,6 +354,10 @@ rec { inherit stdenv curl; }); + makeInitrd = {contents}: import ../build-support/kernel/make-initrd.nix { + inherit stdenv perl cpio contents; + }; + makeSetupHook = script: runCommand "hook" {} '' ensureDir $out/nix-support cp ${script} $out/nix-support/setup-hook @@ -361,6 +365,10 @@ rec { makeWrapper = makeSetupHook ../build-support/make-wrapper/make-wrapper.sh; + makeModulesClosure = {kernel, rootModules}: import ../build-support/kernel/modules-closure.nix { + inherit stdenv module_init_tools kernel rootModules; + }; + # Run the shell command `buildCommand' to produce a store object # named `name'. The attributes in `env' are added to the # environment prior to running the command.