diff options
Diffstat (limited to 'contrib/mkffwnb/mkffwnb.pl')
-rwxr-xr-x | contrib/mkffwnb/mkffwnb.pl | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/contrib/mkffwnb/mkffwnb.pl b/contrib/mkffwnb/mkffwnb.pl new file mode 100755 index 00000000..555ec3ca --- /dev/null +++ b/contrib/mkffwnb/mkffwnb.pl @@ -0,0 +1,226 @@ +#!/usr/bin/perl -w +# +# Perl script to make a bootable image from a floppyfw floppy +# The basic idea is to unpack and replace or convert all +# the necessary config files into the initrd +# and then make a bootable image out of it +# +# The --format= option overrides the default of nbi or elf hardcoded +# in the source. Valid arguments are nbi or elf. +# +# The --output= options specifies an output file instead of stdout +# The --nonet option specifies that a netbootable image is not to +# be built but the vmlinuz and initrd.gz files left behind in $tempdir +# The --localtime=f option specifies a timezone file that's to be +# copied to /etc/localtime in the initrd, allowing a different timezone. +# The --ffw29 option is intended for 2.9.x and above and extends +# the size of the initrd by making a bigger one and copying the original over. +# +# The first non-option argument is taken to be the letter of a floppy to +# convert, e.g. a:, b: or even x: where x: is mapped to a file using +# mtools mapping in $HOME/.mtoolsrc. See the mtools documentation. +# Thus you can work on a floppy image in a disk file and only write +# to a floppy with dd or cp when you need to test the image. + +use Getopt::Long; + +use lib '/usr/local/lib/mkffwnb/'; +use Extendinitrd; + +use strict; + +use vars qw($testing $verbose $localtime $nonet $format $ffw29 $imagefile + $floppy $libdir $tftpdir $output $tempdir $tempmount); + +sub findversion () { + my ($version) = grep(/FloppyFW/, `mtype $imagefile ${floppy}floppyfw.msg`); + return '' unless defined($version) and $version ne ''; + chomp($version); + $version =~ s/.*FloppyFW (\d+\.\d+\.\d+(\.\d+)?).*/$1/; + return ($version); +} + +sub getappendargs () { + my ($append) = join(' ', grep(/^\s*(append\s|console=)/, `mtype $imagefile ${floppy}syslinux.cfg`)); + chomp ($append); + my @args = split(/\s+/, $append); + my @result = (); + foreach $_ (@args) { + next if (/^$/ or /^append/ or /^initrd=/); + next if (!$ffw29 and /^root=/); + push (@result, $_); + } + return (join(' ', @result)); +} + +# Copy whole floppy to the current directory +# m preserves timestamps, n overwrites without warning and / means recursive +sub mcopy ($) { + my ($tempdir) = @_; + + print "mcopy $imagefile -mn/ ${floppy}* $tempdir\n"; + my $status = system("mcopy -mn/ $imagefile ${floppy}* $tempdir"); + return ($status / 256); +} + +# Gunzip file, -f forces overwriting of uncompressed file +sub gunzip ($) { + my ($file) = @_; + + print "Gunzipping $file\n" if ($verbose); + my $status = system('gunzip', '-f', $file); + return ($status / 256); +} + +# Gzip file, -f forces overwriting of compressed file +sub gzip ($) { + my ($file) = @_; + + print "Gzipping $file\n" if ($verbose); + my $status = system('gzip', '-9', '-f', $file); + return ($status / 256); +} + +sub loopbackmount ($$) { + my ($file, $point) = @_; + + print "Mounting $file on $point loopback\n" if ($verbose); + my $status = system('mount', '-o', 'loop', $file, $point); + return ($testing ? 0 : $status / 256); +} + +sub loopbackumount ($) { + my ($point) = @_; + + print "Umounting $point\n" if ($verbose); + my $status = system('umount', $point); + return ($testing ? 0 : $status / 256); +} + +# Convert DOS CR-NL to Unix NL. $dst has implied prefix of $tempmount +# Use @output for temporary storage in case we write back to the same file +sub dostounix ($$) { + my ($src, $dst) = @_; + my @output = (); + + $dst = "$tempmount/$dst"; + print "Converting $src to $dst\n" if ($verbose); + unless (open(S, $src)) { + print "$src: $!\n"; + return (0); + } + while (<S>) { + chomp; + tr /\015//d; + push(@output, $_); + } + close(S); + open(D, ">$dst") or return; + for $_ (@output) { + print D "$_\n"; + } + close(D); + chmod(0755, $dst); + return (1); +} + +sub bunzip2untar ($$) { + my ($file, $dir) = @_; + + print "Unpacking $file into $dir\n" if ($verbose); + system("bunzip2 < $file | (cd $dir; tar xf -)"); +} + +$testing = $< != 0; +$verbose = 1; +$format = ''; +$imagefile = ''; +GetOptions('output=s' => \$output, + 'nonet!' => \$nonet, + 'localtime=s' => \$localtime, + 'format=s' => \$format, + 'ffw29!' => \$ffw29, + 'ffw30!' => \$ffw29, + 'i=s' => \$imagefile); +if (defined($output) and $output !~ m(^/)) { + my $d = `pwd`; + chomp($d); + $output = "$d/$output"; +} +if ($imagefile) { + $imagefile = "-i $imagefile"; +} +$libdir = '/usr/local/lib/mkffwnb'; +$tftpdir = '/usr/local/var/tftpboot'; +# default can also be 'elf' +$format = 'nbi' if ($format ne 'elf' and $format ne 'nbi'); +$floppy = $#ARGV >= 0 ? $ARGV[0] : 'a:'; +print <<EOF; +This program requires mtools, tar, bzip2, loopback mount in the kernel, +and root privileges to execute. Hope you have them. +EOF +my $version = &findversion(); +$version ne '' or die "Cannot determine version\n"; +print "Version $version\n"; +my $append = &getappendargs(); +$append = "--append='$append'" if $append ne ''; +print "$append\n"; +$libdir .= '/' . $version; +-d $libdir or die "Cannot find files for $version\n"; +$tempdir = $nonet ? '/tmp/mkffwnb' : "/tmp/mkffwnb$$"; +$tempmount = 'tmpmount'; +mkdir($tempdir, 0755); +print "Copying files off floppy, please be patient...\n"; +&mcopy($tempdir) == 0 or die "Mcopy failed, diskette problem?\n"; +chdir($tempdir); +&gunzip('initrd.gz') == 0 or die "Gunzip of initrd.gz failed\n"; +if ($ffw29) { + extendinitrd("initrd", 5760); + system("mv newinitrd initrd"); +} +mkdir($tempmount, 0755); +&loopbackmount('initrd', $tempmount) == 0 or die "Loopback mount failed\n"; +&dostounix("$libdir/linuxrc", "linuxrc") if (-r "$libdir/linuxrc"); +unless (&dostounix("$libdir/floppyfw.ini", "floppyfw.ini")) { + &dostounix("floppyfw/floppyfw.ini", $ffw29 ? "etc/floppyfw.ini" : "floppyfw.ini"); +} +&dostounix("config", $ffw29 ? "etc/config.prelogin" : "etc/config"); +for my $i (glob('*.bz2 floppyfw/add.bz2 modules/*.bz2 packages/*.bz2')) { + &bunzip2untar($i, $tempmount); +} +for my $i (glob('packages/*.ini')) { + my $file = $i; + $file =~ s:packages/::; + &dostounix($i, "etc/$file"); +} +&dostounix("hosts", "etc/hosts"); +&dostounix("modules.lst", "etc/modules.lst"); +&dostounix("network.ini", "etc/network.init"); +&dostounix("firewall.ini", "etc/firewall.init"); +&dostounix("syslog.cfg", "etc/syslog.conf"); +&dostounix("packages/timeinfo", "etc/localtime"); +system("cp -p licenses/* $tempmount/licenses/"); +# This conditional code is for 1.1.2 and below +unless (glob('modules/*.bz2')) { + print "Copying additional modules\n" if ($verbose); + system("cp -p modules/* $tempmount/lib/modules/"); +} +# If a timezone file has been specified, copy that onto initrd +if (defined($localtime)) { + if (-r $localtime) { + print "Copying $localtime to $tempmount/etc/localtime\n"; + system("cp -p $localtime $tempmount/etc/localtime"); + } else { + print "$localtime: $!\n"; + } +} +&loopbackumount($tempmount) == 0 or die "Loopback umount failed\n"; +&gzip('initrd') == 0 or die "Gzip of initrd failed\n"; +if ($nonet) { + print "Floppyfw directory in $tempdir\n"; +} else { + print "Calling mk$format-linux to make the netbootable image\n" if ($verbose); + $output = "$tftpdir/floppyfw-$version.nb" if (!defined($output)); + system("mk$format-linux $append --output=$output vmlinuz initrd.gz"); + system("rm -fr $tempdir"); +} |