diff options
-rwxr-xr-x | draklive | 276 | ||||
-rw-r--r-- | lib/MDV/Draklive/Initrd.pm | 280 |
2 files changed, 283 insertions, 273 deletions
@@ -36,9 +36,9 @@ use IO::Handle; #- autoflush use MDV::Draklive::Utils; use MDV::Draklive::Live; use MDV::Draklive::Media; -use MDV::Draklive::StorageFS; use MDV::Draklive::Progress; use MDV::Draklive::Loopback; +use MDV::Draklive::Initrd; my $dir_distrib_sqfs = { mountpoint => '/distrib', @@ -178,13 +178,6 @@ my %storage = ( }, ); -sub nls_modules { - my ($live) = @_; - my $fs = $live->{media}->get_media_setting('fs'); - if_($fs eq 'vfat', 'nls_cp437'), #- default FAT codepage - if_($fs !~ /^ext/, map { "nls_$_" } (map { "iso8859_$_" } 1..7, 9, 13..15), 'utf8'); -} - my %overlay = ( unionfs => { modules => [ qw(unionfs) ], @@ -212,269 +205,6 @@ sub need_media_specific_boot { to_bool(list_selected_loopbacks($live)); } -sub create_media_initrd { - my ($live) = @_; - create_initrd_for_media($live, $live->{media}); - cp_f($live->get_builddir . $live->{prefix}{build}{boot} . $live->{media}->get_initrd_path, - $live->{copy_initrd}) if $live->{copy_initrd}; -} - -sub inst_initrd_file { - my ($root, $initrd_tree, $file) = @_; - if ($file =~ m|/s?bin/|) { - inst_initrd_bin($root, $initrd_tree, $file); - } else { - mkdir_p($initrd_tree . dirname($file)); - inst_initrd_dso_deps($root, $initrd_tree, $file) if $file =~ m|/lib[^/]*/|; - cp_f($root . $file, $initrd_tree . $file) or die "unable to copy $file from system chroot\n"; - } -} - -sub inst_initrd_dso_deps { - my ($root, $initrd_tree, $dso) = @_; - foreach my $file (`chroot $root ldd $dso | awk '/\\// {if(\$2 == "=>") {print \$3} else {print \$1}}'`) { - chomp $file; - $file =~ s!^(/lib[^/]*)/(?:i686|tls)!$1!; - my ($lib_prefix, $filename) = $file =~ m|(/lib[^/]*).*/([^/]+)$| or next; - my $dest = $initrd_tree . $lib_prefix . '/' . $filename; - mkdir_p($initrd_tree . $lib_prefix); - -f $dest || cp_f($root . $file, $dest) or die "unable to copy $filename from system chroot\n"; - } -} -sub inst_initrd_bin { - my ($root, $initrd_tree, $bin) = @_; - cp_f($root . $bin, $initrd_tree . '/bin/'); - inst_initrd_dso_deps($root, $initrd_tree, $bin); -} - -sub create_initrd_for_media { - my ($live, $media) = @_; - - my $lib_prefix = find { glob($live->get_system_root . $_ . '/libc.so.*') } qw(/lib64 /lib); - $lib_prefix or die 'unable to find system libraries in /lib or /lib64'; - - my $initrd_tree = $live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage}; - rm_rf($initrd_tree) if -e $initrd_tree; - - mkdir_p($initrd_tree . $_) foreach - qw(/bin /dev /proc /sys /tmp), - map { $live->{prefix}{live}{mnt} . $_ } - $live->{prefix}{media}{mnt}, - $live->{mount}{root}, - map { $_->{mountpoint} } @{$live->{mount}{dirs} || []}; - - #- use nash with label support - inst_initrd_bin($live->get_system_root, $initrd_tree, '/sbin/nash'); - inst_initrd_bin($live->get_system_root, $initrd_tree, '/usr' . $lib_prefix . '/drakx-installer-binaries/probe-modules'); - inst_initrd_bin($live->get_system_root, $initrd_tree, '/sbin/blockdev') - if $media->get_media_setting('rereadpt'); - inst_initrd_bin($live->get_system_root, $initrd_tree, '/usr/bin/strace') - if $live->{debug}; - - foreach (chomp_(run_program::rooted_get_stdout($live->get_system_root, "/usr/sbin/splashy_find_files"))) { - inst_initrd_file($live->get_system_root, $initrd_tree, $_); - } - - #- busybox is required to: - #- detect usb-storage process (we need sh/while/ps/grep) - #- mount loopbacks read-only with losetup (useful over NFS) - my $busybox = '/usr/bin/busybox'; - inst_initrd_bin($live->get_system_root, $initrd_tree, $busybox); - my $busybox_rooted = $live->get_system_root . $busybox; - my @l = map { /functions:/ .. /^$/ ? do { s/\s//g; split /,/ } : () } `$busybox_rooted`; - shift @l; - symlink('busybox', $initrd_tree . "/bin/$_") foreach @l; - - my $fs = $media->get_media_setting('fs'); - my @used_loop_types = uniq(map { $_->{type} } @{$live->{mount}{dirs}}); - inst_initrd_bin($live->get_system_root, $initrd_tree, $_) foreach - MDV::Draklive::StorageFS::get_files($fs), - (map { @{$loop_types{$_} && $loop_types{$_}{files} || []} } @used_loop_types); - - output_p($initrd_tree . '/etc/fstab', ''); - output_p($initrd_tree . '/etc/mtab', ''); - - my $loop_nb = 254; - my $rrpt_dev = $media->get_media_setting('rereadpt'); - require devices; - devices::make($initrd_tree . "/dev/$_") foreach - if_($rrpt_dev, $rrpt_dev), - qw(console initrd null ram systty), - (map { "tty$_" } 0..8), - (map { "loop$_" } 0 .. $loop_nb); - syscall_('mknod', $initrd_tree . "/dev/fb0", c::S_IFCHR(), makedev(29, 0)) or die "mknod failed (dev $_): $!"; - #- pre-create devfsd compatibility loop devices (since busybox is still built with devfsd support) - mkdir_p($initrd_tree . "/dev/loop"); - cp_af($initrd_tree . "/dev/loop$_", $initrd_tree . "/dev/loop/$_") foreach 0 .. $loop_nb; - - my $kernel = $live->find_kernel; - print "using kernel $kernel\n"; - my $kernel_root = "/lib/modules/" . $kernel; - list_modules::load_dependencies($live->get_system_root . $kernel_root . "/modules.dep"); - - my ($storage_modules, $skipped) = partition { list_modules::modname2filename($_) } - uniq(map { modules::cond_mapping_24_26($_) } category2modules($media->get_media_setting('modules'))); - my ($extra_modules, $extra_missing) = partition { list_modules::modname2filename($_) } - category2modules($media->get_media_setting('media_modules')), - nls_modules($live), - $media->get_media_fs_module, - @{$media->get_media_setting('extra_modules') || []}, - (map { @{$loop_types{$_}{modules} || []} } uniq(map { $_->{type} } @{$live->{mount}{dirs} || []})), - ($live->{mount}{overlay} ? @{$overlay{$live->{mount}{overlay}}{modules} || []} : ()); - - my @additional_modules = map { if_(m!([^/]+)\.ko(?:\.gz)?!, list_modules::filename2modname($1)) } @{$live->{system}{additional_modules}}; - @$extra_modules = difference2($extra_modules, \@additional_modules); - if (@{$live->{system}{exclude_modules} || []}) { - print STDERR "excluding modules: " . join(' ', @{$live->{system}{exclude_modules}}) . "\n"; - @$_ = difference2($_, $live->{system}{exclude_modules}) foreach $storage_modules, $extra_modules; - } - - my @missing = sort(difference2($extra_missing, \@additional_modules)); - @missing and die "missing mandatory modules:\n" . join("\n", @missing, ''); - - mkdir_p($initrd_tree . $kernel_root . "/kernel"); - my @modules = (@$storage_modules, @$extra_modules); - my @modules_closure = uniq(map { list_modules::dependencies_closure($_) } @modules); - foreach my $m (@modules_closure) { - my $full = list_modules::modname2path($m); - mkdir_p(dirname($initrd_tree . $full)); - cp_f($live->get_system_root . $full, $initrd_tree . $full); - } - foreach my $f (@{$live->{system}{additional_modules}}) { - my $destdir = $initrd_tree . $kernel_root . "/kernel"; - if ($f =~ /.gz$/) { - cp_f($live->{settings}{config_root} . '/' . $f, $destdir); - } else { - my $m = basename($f); - run_program::run('gzip', '>', "$destdir/$m.gz", '-c', $live->{settings}{config_root} . '/' . $f); - } - } - run_('depmod', '-b', $initrd_tree, $kernel); - - mkdir_p($initrd_tree . "/etc/blkid"); #- for nash and showlabels cache - mkdir_p($initrd_tree . "/lib/module-init-tools"); - cp_f($live->get_system_root . "/lib/module-init-tools/ldetect-lst-modules.alias", $initrd_tree . "/lib/module-init-tools"); - mkdir_p($initrd_tree . "/usr/share/ldetect-lst"); - cp_f($live->get_system_root . "/usr/share/pci.ids", $initrd_tree . "/usr/share"); - cp_f($live->get_system_root . "/usr/share/ldetect-lst/" . $_, $initrd_tree . "/usr/share/ldetect-lst") - foreach qw(fallback-modules.alias pcitable.gz usbtable.gz); - - @$skipped and print STDERR "skipped modules: " . join(' ', sort(@$skipped)) . "\n"; - - my @extra_modules_closure = map { list_modules::modname2filename($_) } - uniq(map { list_modules::dependencies_closure($_) } @$extra_modules); - create_initrd_scriptlet($live, $media, @extra_modules_closure, @additional_modules); - compress_initrd_tree($live, $media); - add_splash($live, $media); -} - -sub create_initrd_scriptlet { - my ($live, $media, @modules) = @_; - my $target = $live->{prefix}{live}{mnt} . ($live->{mount}{root} || $live->{prefix}{media}{mnt}); - my $pre = $media->get_media_setting('pre'); - my $fs = $media->get_media_setting('fs'); - my $rrpt_dev = $media->get_media_setting('rereadpt'); - my $debug_shell = "sh -c 'if grep -q initrd_debug /proc/cmdline; then exec sh </dev/console >/dev/console 2>/dev/console; fi'"; - my ($mount_first, $mount_last) = partition { !$loop_types{$_->{type}}{delay_mount} } - grep { exists $loop_types{$_->{type}}{mount} } @{$live->{mount}{dirs} || []}; - - output_with_perm($live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage} . '/linuxrc', 0755, - join("\n", - "#!/bin/nash", - #- required for labels and ps - "nash-mount -t proc /proc /proc", - #- required for cdrom labels - "nash-mount -t sysfs /sys /sys", - "splashy_chvt 8", - "splashy boot", - (map { join(" ", "probe-modules", list_modules::filename2modname($_), grep { $_ } $live->{system}{module_options}{$_}) } @modules), - "probe-modules --$media->{storage}", - if_($rrpt_dev, - "echo *** Waiting for new partitions on device ${rrpt_dev} ***", - "sh -c 'while ! ls /sys/block/${rrpt_dev}/${rrpt_dev}* >/dev/null 2>&1; do sleep 3; blockdev --rereadpt /dev/${rrpt_dev} >/dev/null 2>&1; done'"), - $debug_shell, - if_($pre, deref_array($pre)), - "mkdevices /dev", - "showlabels --removable", - MDV::Draklive::StorageFS::get_mount($fs)->($live, $media), - (map { $loop_types{$_->{type}}{mount}->($live, $_) } @$mount_first, @$mount_last), - ($live->{mount}{overlay} ? $overlay{$live->{mount}{overlay}}{mount}->($live) : ()), - if_($live->{system}{initrd_pre_pivot}, deref_array($live->{system}{initrd_pre_pivot})), - qq(splashy_update "chroot $target"), - "echo 0x0100 > /proc/sys/kernel/real-root-dev", - "umount /sys", - "sh -c 'umount /proc/bus/usb 2>/dev/null'", - "umount /proc", - "pivot_root $target $target/initrd", - q(sh -c 'rmdir /initrd/live/union'), - q(sh -c 'if [ -d /initrd/live/modules ]; then cd /initrd/live/modules; for i in `ls -1`; do mkdir -p /live/modules/$i; mount -n --move $i /live/modules/$i; rmdir $i; done; rmdir /initrd/live/modules; fi'), - q(sh -c 'cd /initrd/live; for i in `ls -1`; do [ -d $i ] || continue; mkdir -p /live/$i; mount -n --move $i /live/$i; rmdir $i; done'), - q(sh -c 'mv /initrd/live/* /live/'), - q(rmdir /initrd/live), - if_($live->{system}{initrd_post}, deref_array($live->{system}{initrd_post})), - "")); -} - -sub compress_initrd_tree { - my ($live, $media) = @_; - - my $initrd_tree = $live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage}; - my $size = chomp_(run_program::get_stdout("du -ks $initrd_tree | awk '{print \$1}'")); - my $inodes = chomp_(run_program::get_stdout("find $initrd_tree | wc -l")) + 100; - my $initrd_size = $size + 350 + int($inodes / 10); #- 10 inodes needs 1K - $initrd_size += 600; # splashy - my $initrd = $live->get_builddir . $live->{prefix}{build}{boot} . $media->get_initrd_path; - $initrd =~ s/.gz$//; - - mkdir_p(dirname($initrd)); - run_('dd', 'if=/dev/zero', "of=$initrd", 'bs=1k', "count=$initrd_size"); - run_('mke2fs', '-q', '-m', 0, '-F', '-N', $inodes, '-s', 1, $initrd); - mkdir_p($live->{mnt}); - run_('mount', '-o', 'loop', '-t', 'ext2', $initrd, $live->{mnt}); - cp_af(glob("$initrd_tree/*"), $live->{mnt}); - rm_rf($live->{mnt} . "/lost+found"); - my $left = chomp_(run_program::get_stdout("df -Pk $live->{mnt} | tail -n 1 | awk '{ print \$4 }'")); - run_('umount', $live->{mnt}); - $left < 200 and die "not enough room to create initrd (only ${left}K left)\n"; - run_('gzip', '-f', '-9', $initrd); -} - -sub add_splash { - my ($live, $media) = @_; - if ($live->{system}{vga_mode} && $live->{system}{splash} ne 'no') { - require bootloader; - my $initrd = $live->get_builddir . $live->{prefix}{build}{boot} . $media->get_initrd_path; - my $tmp_initrd = '/tmp/initrd.gz'; - cp_f($initrd, $live->get_system_root . $tmp_initrd); - { - local $::prefix = $live->get_system_root; - bootloader::add_boot_splash($tmp_initrd, $live->{system}{vga_mode}); - } - cp_f($live->get_system_root . $tmp_initrd, $initrd); - unlink($live->get_system_root . $tmp_initrd); - } -} - -sub create_classical_initrd { - my ($live) = @_; - my $kernel = $live->find_kernel; - #- FIXME: use bootloader-config and allow it not to require a bootloader? - print "using kernel $kernel\n"; - my $initrd_long = '/boot/initrd-'. $kernel . '.img'; - my $initrd_short = '/boot/initrd.img'; - my $vmlinuz_long = '/boot/vmlinuz-' . $kernel; - my $vmlinuz_short = '/boot/vmlinuz'; - my $root = $live->get_system_root; - run_({ root => $root }, 'mkinitrd', '-v', '-f', $initrd_long, $kernel); - symlinkf(basename($initrd_long), $root . $initrd_short); - symlinkf(basename($vmlinuz_long), $root . $vmlinuz_short); - if ($live->{system}{vga_mode} && $live->{system}{splash} ne 'no') { - require bootloader; - local $::prefix = $live->get_system_root; - bootloader::add_boot_splash($initrd_long, $live->{system}{vga_mode}); - } -} - sub get_default_append { my ($live, $opts) = @_; join(' ', @@ -873,9 +603,9 @@ sub prepare_bootloader { sub create_initrd { my ($live) = @_; if (need_media_specific_boot($live)) { - create_media_initrd($live); + MDV::Draklive::Initrd::create_media_initrd($live); } else { - create_classical_initrd($live); + MDV::Draklive::Initrd::create_classical_initrd($live); } } diff --git a/lib/MDV/Draklive/Initrd.pm b/lib/MDV/Draklive/Initrd.pm new file mode 100644 index 0000000..95755b6 --- /dev/null +++ b/lib/MDV/Draklive/Initrd.pm @@ -0,0 +1,280 @@ +package MDV::Draklive::Initrd; + +use MDK::Common; +use common; +use list_modules; +use MDV::Draklive::Utils; +use MDV::Draklive::StorageFS; +use MDV::Draklive::Loopback; + +sub nls_modules { + my ($live) = @_; + my $fs = $live->{media}->get_media_setting('fs'); + if_($fs eq 'vfat', 'nls_cp437'), #- default FAT codepage + if_($fs !~ /^ext/, map { "nls_$_" } (map { "iso8859_$_" } 1..7, 9, 13..15), 'utf8'); +} + +sub create_media_initrd { + my ($live) = @_; + create_initrd_for_media($live, $live->{media}); + cp_f($live->get_builddir . $live->{prefix}{build}{boot} . $live->{media}->get_initrd_path, + $live->{copy_initrd}) if $live->{copy_initrd}; +} + +sub inst_initrd_file { + my ($root, $initrd_tree, $file) = @_; + if ($file =~ m|/s?bin/|) { + inst_initrd_bin($root, $initrd_tree, $file); + } else { + mkdir_p($initrd_tree . dirname($file)); + inst_initrd_dso_deps($root, $initrd_tree, $file) if $file =~ m|/lib[^/]*/|; + cp_f($root . $file, $initrd_tree . $file) or die "unable to copy $file from system chroot\n"; + } +} + +sub inst_initrd_dso_deps { + my ($root, $initrd_tree, $dso) = @_; + foreach my $file (`chroot $root ldd $dso | awk '/\\// {if(\$2 == "=>") {print \$3} else {print \$1}}'`) { + chomp $file; + $file =~ s!^(/lib[^/]*)/(?:i686|tls)!$1!; + my ($lib_prefix, $filename) = $file =~ m|(/lib[^/]*).*/([^/]+)$| or next; + my $dest = $initrd_tree . $lib_prefix . '/' . $filename; + mkdir_p($initrd_tree . $lib_prefix); + -f $dest || cp_f($root . $file, $dest) or die "unable to copy $filename from system chroot\n"; + } +} +sub inst_initrd_bin { + my ($root, $initrd_tree, $bin) = @_; + cp_f($root . $bin, $initrd_tree . '/bin/'); + inst_initrd_dso_deps($root, $initrd_tree, $bin); +} + +sub create_initrd_for_media { + my ($live, $media) = @_; + + my $lib_prefix = find { glob($live->get_system_root . $_ . '/libc.so.*') } qw(/lib64 /lib); + $lib_prefix or die 'unable to find system libraries in /lib or /lib64'; + + my $initrd_tree = $live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage}; + rm_rf($initrd_tree) if -e $initrd_tree; + + mkdir_p($initrd_tree . $_) foreach + qw(/bin /dev /proc /sys /tmp), + map { $live->{prefix}{live}{mnt} . $_ } + $live->{prefix}{media}{mnt}, + $live->{mount}{root}, + map { $_->{mountpoint} } @{$live->{mount}{dirs} || []}; + + #- use nash with label support + inst_initrd_bin($live->get_system_root, $initrd_tree, '/sbin/nash'); + inst_initrd_bin($live->get_system_root, $initrd_tree, '/usr' . $lib_prefix . '/drakx-installer-binaries/probe-modules'); + inst_initrd_bin($live->get_system_root, $initrd_tree, '/sbin/blockdev') + if $media->get_media_setting('rereadpt'); + inst_initrd_bin($live->get_system_root, $initrd_tree, '/usr/bin/strace') + if $live->{debug}; + + foreach (chomp_(run_program::rooted_get_stdout($live->get_system_root, "/usr/sbin/splashy_find_files"))) { + inst_initrd_file($live->get_system_root, $initrd_tree, $_); + } + + #- busybox is required to: + #- detect usb-storage process (we need sh/while/ps/grep) + #- mount loopbacks read-only with losetup (useful over NFS) + my $busybox = '/usr/bin/busybox'; + inst_initrd_bin($live->get_system_root, $initrd_tree, $busybox); + my $busybox_rooted = $live->get_system_root . $busybox; + my @l = map { /functions:/ .. /^$/ ? do { s/\s//g; split /,/ } : () } `$busybox_rooted`; + shift @l; + symlink('busybox', $initrd_tree . "/bin/$_") foreach @l; + + my $fs = $media->get_media_setting('fs'); + my @used_loop_types = uniq(map { $_->{type} } @{$live->{mount}{dirs}}); + inst_initrd_bin($live->get_system_root, $initrd_tree, $_) foreach + MDV::Draklive::StorageFS::get_files($fs), + (map { @{$loop_types{$_} && $loop_types{$_}{files} || []} } @used_loop_types); + + output_p($initrd_tree . '/etc/fstab', ''); + output_p($initrd_tree . '/etc/mtab', ''); + + my $loop_nb = 254; + my $rrpt_dev = $media->get_media_setting('rereadpt'); + require devices; + devices::make($initrd_tree . "/dev/$_") foreach + if_($rrpt_dev, $rrpt_dev), + qw(console initrd null ram systty), + (map { "tty$_" } 0..8), + (map { "loop$_" } 0 .. $loop_nb); + syscall_('mknod', $initrd_tree . "/dev/fb0", c::S_IFCHR(), makedev(29, 0)) or die "mknod failed (dev $_): $!"; + #- pre-create devfsd compatibility loop devices (since busybox is still built with devfsd support) + mkdir_p($initrd_tree . "/dev/loop"); + cp_af($initrd_tree . "/dev/loop$_", $initrd_tree . "/dev/loop/$_") foreach 0 .. $loop_nb; + + my $kernel = $live->find_kernel; + print "using kernel $kernel\n"; + my $kernel_root = "/lib/modules/" . $kernel; + list_modules::load_dependencies($live->get_system_root . $kernel_root . "/modules.dep"); + + my ($storage_modules, $skipped) = partition { list_modules::modname2filename($_) } + uniq(map { modules::cond_mapping_24_26($_) } category2modules($media->get_media_setting('modules'))); + my ($extra_modules, $extra_missing) = partition { list_modules::modname2filename($_) } + category2modules($media->get_media_setting('media_modules')), + nls_modules($live), + $media->get_media_fs_module, + @{$media->get_media_setting('extra_modules') || []}, + (map { @{$loop_types{$_}{modules} || []} } uniq(map { $_->{type} } @{$live->{mount}{dirs} || []})), + ($live->{mount}{overlay} ? @{$overlay{$live->{mount}{overlay}}{modules} || []} : ()); + + my @additional_modules = map { if_(m!([^/]+)\.ko(?:\.gz)?!, list_modules::filename2modname($1)) } @{$live->{system}{additional_modules}}; + @$extra_modules = difference2($extra_modules, \@additional_modules); + if (@{$live->{system}{exclude_modules} || []}) { + print STDERR "excluding modules: " . join(' ', @{$live->{system}{exclude_modules}}) . "\n"; + @$_ = difference2($_, $live->{system}{exclude_modules}) foreach $storage_modules, $extra_modules; + } + + my @missing = sort(difference2($extra_missing, \@additional_modules)); + @missing and die "missing mandatory modules:\n" . join("\n", @missing, ''); + + mkdir_p($initrd_tree . $kernel_root . "/kernel"); + my @modules = (@$storage_modules, @$extra_modules); + my @modules_closure = uniq(map { list_modules::dependencies_closure($_) } @modules); + foreach my $m (@modules_closure) { + my $full = list_modules::modname2path($m); + mkdir_p(dirname($initrd_tree . $full)); + cp_f($live->get_system_root . $full, $initrd_tree . $full); + } + foreach my $f (@{$live->{system}{additional_modules}}) { + my $destdir = $initrd_tree . $kernel_root . "/kernel"; + if ($f =~ /.gz$/) { + cp_f($live->{settings}{config_root} . '/' . $f, $destdir); + } else { + my $m = basename($f); + run_program::run('gzip', '>', "$destdir/$m.gz", '-c', $live->{settings}{config_root} . '/' . $f); + } + } + run_('depmod', '-b', $initrd_tree, $kernel); + + mkdir_p($initrd_tree . "/etc/blkid"); #- for nash and showlabels cache + mkdir_p($initrd_tree . "/lib/module-init-tools"); + cp_f($live->get_system_root . "/lib/module-init-tools/ldetect-lst-modules.alias", $initrd_tree . "/lib/module-init-tools"); + mkdir_p($initrd_tree . "/usr/share/ldetect-lst"); + cp_f($live->get_system_root . "/usr/share/pci.ids", $initrd_tree . "/usr/share"); + cp_f($live->get_system_root . "/usr/share/ldetect-lst/" . $_, $initrd_tree . "/usr/share/ldetect-lst") + foreach qw(fallback-modules.alias pcitable.gz usbtable.gz); + + @$skipped and print STDERR "skipped modules: " . join(' ', sort(@$skipped)) . "\n"; + + my @extra_modules_closure = map { list_modules::modname2filename($_) } + uniq(map { list_modules::dependencies_closure($_) } @$extra_modules); + create_initrd_scriptlet($live, $media, @extra_modules_closure, @additional_modules); + compress_initrd_tree($live, $media); + add_splash($live, $media); +} + +sub create_initrd_scriptlet { + my ($live, $media, @modules) = @_; + my $target = $live->{prefix}{live}{mnt} . ($live->{mount}{root} || $live->{prefix}{media}{mnt}); + my $pre = $media->get_media_setting('pre'); + my $fs = $media->get_media_setting('fs'); + my $rrpt_dev = $media->get_media_setting('rereadpt'); + my $debug_shell = "sh -c 'if grep -q initrd_debug /proc/cmdline; then exec sh </dev/console >/dev/console 2>/dev/console; fi'"; + my ($mount_first, $mount_last) = partition { !$loop_types{$_->{type}}{delay_mount} } + grep { exists $loop_types{$_->{type}}{mount} } @{$live->{mount}{dirs} || []}; + + output_with_perm($live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage} . '/linuxrc', 0755, + join("\n", + "#!/bin/nash", + #- required for labels and ps + "nash-mount -t proc /proc /proc", + #- required for cdrom labels + "nash-mount -t sysfs /sys /sys", + "splashy_chvt 8", + "splashy boot", + (map { join(" ", "probe-modules", list_modules::filename2modname($_), grep { $_ } $live->{system}{module_options}{$_}) } @modules), + "probe-modules --$media->{storage}", + if_($rrpt_dev, + "echo *** Waiting for new partitions on device ${rrpt_dev} ***", + "sh -c 'while ! ls /sys/block/${rrpt_dev}/${rrpt_dev}* >/dev/null 2>&1; do sleep 3; blockdev --rereadpt /dev/${rrpt_dev} >/dev/null 2>&1; done'"), + $debug_shell, + if_($pre, deref_array($pre)), + "mkdevices /dev", + "showlabels --removable", + MDV::Draklive::StorageFS::get_mount($fs)->($live, $media), + (map { $loop_types{$_->{type}}{mount}->($live, $_) } @$mount_first, @$mount_last), + ($live->{mount}{overlay} ? $overlay{$live->{mount}{overlay}}{mount}->($live) : ()), + if_($live->{system}{initrd_pre_pivot}, deref_array($live->{system}{initrd_pre_pivot})), + qq(splashy_update "chroot $target"), + "echo 0x0100 > /proc/sys/kernel/real-root-dev", + "umount /sys", + "sh -c 'umount /proc/bus/usb 2>/dev/null'", + "umount /proc", + "pivot_root $target $target/initrd", + q(sh -c 'rmdir /initrd/live/union'), + q(sh -c 'if [ -d /initrd/live/modules ]; then cd /initrd/live/modules; for i in `ls -1`; do mkdir -p /live/modules/$i; mount -n --move $i /live/modules/$i; rmdir $i; done; rmdir /initrd/live/modules; fi'), + q(sh -c 'cd /initrd/live; for i in `ls -1`; do [ -d $i ] || continue; mkdir -p /live/$i; mount -n --move $i /live/$i; rmdir $i; done'), + q(sh -c 'mv /initrd/live/* /live/'), + q(rmdir /initrd/live), + if_($live->{system}{initrd_post}, deref_array($live->{system}{initrd_post})), + "")); +} + +sub compress_initrd_tree { + my ($live, $media) = @_; + + my $initrd_tree = $live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage}; + my $size = chomp_(run_program::get_stdout("du -ks $initrd_tree | awk '{print \$1}'")); + my $inodes = chomp_(run_program::get_stdout("find $initrd_tree | wc -l")) + 100; + my $initrd_size = $size + 350 + int($inodes / 10); #- 10 inodes needs 1K + $initrd_size += 600; # splashy + my $initrd = $live->get_builddir . $live->{prefix}{build}{boot} . $media->get_initrd_path; + $initrd =~ s/.gz$//; + + mkdir_p(dirname($initrd)); + run_('dd', 'if=/dev/zero', "of=$initrd", 'bs=1k', "count=$initrd_size"); + run_('mke2fs', '-q', '-m', 0, '-F', '-N', $inodes, '-s', 1, $initrd); + mkdir_p($live->{mnt}); + run_('mount', '-o', 'loop', '-t', 'ext2', $initrd, $live->{mnt}); + cp_af(glob("$initrd_tree/*"), $live->{mnt}); + rm_rf($live->{mnt} . "/lost+found"); + my $left = chomp_(run_program::get_stdout("df -Pk $live->{mnt} | tail -n 1 | awk '{ print \$4 }'")); + run_('umount', $live->{mnt}); + $left < 200 and die "not enough room to create initrd (only ${left}K left)\n"; + run_('gzip', '-f', '-9', $initrd); +} + +sub add_splash { + my ($live, $media) = @_; + if ($live->{system}{vga_mode} && $live->{system}{splash} ne 'no') { + require bootloader; + my $initrd = $live->get_builddir . $live->{prefix}{build}{boot} . $media->get_initrd_path; + my $tmp_initrd = '/tmp/initrd.gz'; + cp_f($initrd, $live->get_system_root . $tmp_initrd); + { + local $::prefix = $live->get_system_root; + bootloader::add_boot_splash($tmp_initrd, $live->{system}{vga_mode}); + } + cp_f($live->get_system_root . $tmp_initrd, $initrd); + unlink($live->get_system_root . $tmp_initrd); + } +} + +sub create_classical_initrd { + my ($live) = @_; + my $kernel = $live->find_kernel; + #- FIXME: use bootloader-config and allow it not to require a bootloader? + print "using kernel $kernel\n"; + my $initrd_long = '/boot/initrd-'. $kernel . '.img'; + my $initrd_short = '/boot/initrd.img'; + my $vmlinuz_long = '/boot/vmlinuz-' . $kernel; + my $vmlinuz_short = '/boot/vmlinuz'; + my $root = $live->get_system_root; + run_({ root => $root }, 'mkinitrd', '-v', '-f', $initrd_long, $kernel); + symlinkf(basename($initrd_long), $root . $initrd_short); + symlinkf(basename($vmlinuz_long), $root . $vmlinuz_short); + if ($live->{system}{vga_mode} && $live->{system}{splash} ne 'no') { + require bootloader; + local $::prefix = $live->get_system_root; + bootloader::add_boot_splash($initrd_long, $live->{system}{vga_mode}); + } +} + +1; |