3 # Perl script to make a bootable image from a floppyfw floppy
4 # The basic idea is to unpack and replace or convert all
5 # the necessary config files into the initrd
6 # and then make a bootable image out of it
8 # The --format= option overrides the default of nbi or elf hardcoded
9 # in the source. Valid arguments are nbi or elf.
11 # The --output= options specifies an output file instead of stdout
12 # The --nonet option specifies that a netbootable image is not to
13 # be built but the vmlinuz and initrd.gz files left behind in $tempdir
14 # The --localtime=f option specifies a timezone file that's to be
15 # copied to /etc/localtime in the initrd, allowing a different timezone.
16 # The --ffw29 option is intended for 2.9.x and above and extends
17 # the size of the initrd by making a bigger one and copying the original over.
19 # The first non-option argument is taken to be the letter of a floppy to
20 # convert, e.g. a:, b: or even x: where x: is mapped to a file using
21 # mtools mapping in $HOME/.mtoolsrc. See the mtools documentation.
22 # Thus you can work on a floppy image in a disk file and only write
23 # to a floppy with dd or cp when you need to test the image.
27 use lib
'/usr/local/lib/mkffwnb/';
32 use vars
qw($testing $verbose $localtime $nonet $format $ffw29 $imagefile
33 $floppy $libdir $tftpdir $output $tempdir $tempmount);
36 my ($version) = grep(/FloppyFW/, `mtype $imagefile ${floppy}floppyfw.msg`);
37 return '' unless defined($version) and $version ne '';
39 $version =~ s/.*FloppyFW (\d+\.\d+\.\d+(\.\d+)?).*/$1/;
43 sub getappendargs () {
44 my ($append) = join(' ', grep(/^\s*(append\s|console=)/, `mtype $imagefile ${floppy}syslinux.cfg`));
46 my @args = split(/\s+/, $append);
49 next if (/^$/ or /^append/ or /^initrd=/);
50 next if (!$ffw29 and /^root=/);
53 return (join(' ', @result));
56 # Copy whole floppy to the current directory
57 # m preserves timestamps, n overwrites without warning and / means recursive
61 print "mcopy $imagefile -mn/ ${floppy}* $tempdir\n";
62 my $status = system("mcopy -mn/ $imagefile ${floppy}* $tempdir");
63 return ($status / 256);
66 # Gunzip file, -f forces overwriting of uncompressed file
70 print "Gunzipping $file\n" if ($verbose);
71 my $status = system('gunzip', '-f', $file);
72 return ($status / 256);
75 # Gzip file, -f forces overwriting of compressed file
79 print "Gzipping $file\n" if ($verbose);
80 my $status = system('gzip', '-9', '-f', $file);
81 return ($status / 256);
84 sub loopbackmount ($$) {
85 my ($file, $point) = @_;
87 print "Mounting $file on $point loopback\n" if ($verbose);
88 my $status = system('mount', '-o', 'loop', $file, $point);
89 return ($testing ? 0 : $status / 256);
92 sub loopbackumount ($) {
95 print "Umounting $point\n" if ($verbose);
96 my $status = system('umount', $point);
97 return ($testing ? 0 : $status / 256);
100 # Convert DOS CR-NL to Unix NL. $dst has implied prefix of $tempmount
101 # Use @output for temporary storage in case we write back to the same file
103 my ($src, $dst) = @_;
106 $dst = "$tempmount/$dst";
107 print "Converting $src to $dst\n" if ($verbose);
108 unless (open(S, $src)) {
118 open(D, ">$dst") or return;
127 sub bunzip2untar ($$) {
128 my ($file, $dir) = @_;
130 print "Unpacking $file into $dir\n" if ($verbose);
131 system("bunzip2 < $file | (cd $dir; tar xf -)");
138 GetOptions('output=s' => \$output,
140 'localtime=s' => \$localtime,
141 'format=s' => \$format,
144 'i=s' => \$imagefile);
145 if (defined($output) and $output !~ m(^/)) {
148 $output = "$d/$output";
151 $imagefile = "-i $imagefile";
153 $libdir = '/usr/local/lib/mkffwnb';
154 $tftpdir = '/usr/local/var/tftpboot';
155 # default can also be 'elf'
156 $format = 'nbi' if ($format ne 'elf' and $format ne 'nbi');
157 $floppy = $#ARGV >= 0 ? $ARGV[0] : 'a:';
159 This program requires mtools, tar, bzip2, loopback mount in the kernel,
160 and root privileges to execute. Hope you have them.
162 my $version = &findversion
();
163 $version ne '' or die "Cannot determine version\n";
164 print "Version $version\n";
165 my $append = &getappendargs
();
166 $append = "--append='$append'" if $append ne '';
168 $libdir .= '/' . $version;
169 -d
$libdir or die "Cannot find files for $version\n";
170 $tempdir = $nonet ?
'/tmp/mkffwnb' : "/tmp/mkffwnb$$";
171 $tempmount = 'tmpmount';
172 mkdir($tempdir, 0755);
173 print "Copying files off floppy, please be patient...\n";
174 &mcopy
($tempdir) == 0 or die "Mcopy failed, diskette problem?\n";
176 &gunzip
('initrd.gz') == 0 or die "Gunzip of initrd.gz failed\n";
178 extendinitrd
("initrd", 5760);
179 system("mv newinitrd initrd");
181 mkdir($tempmount, 0755);
182 &loopbackmount
('initrd', $tempmount) == 0 or die "Loopback mount failed\n";
183 &dostounix
("$libdir/linuxrc", "linuxrc") if (-r
"$libdir/linuxrc");
184 unless (&dostounix
("$libdir/floppyfw.ini", "floppyfw.ini")) {
185 &dostounix
("floppyfw/floppyfw.ini", $ffw29 ?
"etc/floppyfw.ini" : "floppyfw.ini");
187 &dostounix
("config", $ffw29 ?
"etc/config.prelogin" : "etc/config");
188 for my $i (glob('*.bz2 floppyfw/add.bz2 modules/*.bz2 packages/*.bz2')) {
189 &bunzip2untar
($i, $tempmount);
191 for my $i (glob('packages/*.ini')) {
193 $file =~ s
:packages
/::;
194 &dostounix
($i, "etc/$file");
196 &dostounix
("hosts", "etc/hosts");
197 &dostounix
("modules.lst", "etc/modules.lst");
198 &dostounix
("network.ini", "etc/network.init");
199 &dostounix
("firewall.ini", "etc/firewall.init");
200 &dostounix
("syslog.cfg", "etc/syslog.conf");
201 &dostounix
("packages/timeinfo", "etc/localtime");
202 system("cp -p licenses/* $tempmount/licenses/");
203 # This conditional code is for 1.1.2 and below
204 unless (glob('modules/*.bz2')) {
205 print "Copying additional modules\n" if ($verbose);
206 system("cp -p modules/* $tempmount/lib/modules/");
208 # If a timezone file has been specified, copy that onto initrd
209 if (defined($localtime)) {
211 print "Copying $localtime to $tempmount/etc/localtime\n";
212 system("cp -p $localtime $tempmount/etc/localtime");
214 print "$localtime: $!\n";
217 &loopbackumount
($tempmount) == 0 or die "Loopback umount failed\n";
218 &gzip
('initrd') == 0 or die "Gzip of initrd failed\n";
220 print "Floppyfw directory in $tempdir\n";
222 print "Calling mk$format-linux to make the netbootable image\n" if ($verbose);
223 $output = "$tftpdir/floppyfw-$version.nb" if (!defined($output));
224 system("mk$format-linux $append --output=$output vmlinuz initrd.gz");
225 system("rm -fr $tempdir");