[tg3] Add support for tg3-5721
[people/mdeck/gpxe.git] / contrib / mkffwnb / mkffwnb.pl
1 #!/usr/bin/perl -w
2 #
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
7 #
8 # The --format= option overrides the default of nbi or elf hardcoded
9 # in the source. Valid arguments are nbi or elf.
10 #
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.
18 #
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.
24
25 use Getopt::Long;
26
27 use lib '/usr/local/lib/mkffwnb/';
28 use Extendinitrd;
29
30 use strict;
31
32 use vars qw($testing $verbose $localtime $nonet $format $ffw29 $imagefile
33         $floppy $libdir $tftpdir $output $tempdir $tempmount);
34
35 sub findversion () {
36         my ($version) = grep(/FloppyFW/, `mtype $imagefile ${floppy}floppyfw.msg`);
37         return '' unless defined($version) and $version ne '';
38         chomp($version);
39         $version =~ s/.*FloppyFW (\d+\.\d+\.\d+(\.\d+)?).*/$1/;
40         return ($version);
41 }
42
43 sub getappendargs () {
44         my ($append) = join(' ', grep(/^\s*(append\s|console=)/, `mtype $imagefile ${floppy}syslinux.cfg`));
45         chomp ($append);
46         my @args = split(/\s+/, $append);
47         my @result = ();
48         foreach $_ (@args) {
49                 next if (/^$/ or /^append/ or /^initrd=/);
50                 next if (!$ffw29 and /^root=/);
51                 push (@result, $_);
52         }
53         return (join(' ', @result));
54 }
55
56 # Copy whole floppy to the current directory
57 # m preserves timestamps, n overwrites without warning and / means recursive
58 sub mcopy ($) {
59         my ($tempdir) = @_;
60
61         print "mcopy $imagefile -mn/ ${floppy}* $tempdir\n";
62         my $status = system("mcopy -mn/ $imagefile ${floppy}* $tempdir");
63         return ($status / 256);
64 }
65
66 # Gunzip file, -f forces overwriting of uncompressed file
67 sub gunzip ($) {
68         my ($file) = @_;
69
70         print "Gunzipping $file\n" if ($verbose);
71         my $status = system('gunzip', '-f', $file);
72         return ($status / 256);
73 }
74
75 # Gzip file, -f forces overwriting of compressed file
76 sub gzip ($) {
77         my ($file) = @_;
78
79         print "Gzipping $file\n" if ($verbose);
80         my $status = system('gzip', '-9', '-f', $file);
81         return ($status / 256);
82 }
83
84 sub loopbackmount ($$) {
85         my ($file, $point) = @_;
86
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);
90 }
91
92 sub loopbackumount ($) {
93         my ($point) = @_;
94
95         print "Umounting $point\n" if ($verbose);
96         my $status = system('umount', $point);
97         return ($testing ? 0 : $status / 256);
98 }
99
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
102 sub dostounix ($$) {
103         my ($src, $dst) = @_;
104         my @output = ();
105
106         $dst = "$tempmount/$dst";
107         print "Converting $src to $dst\n" if ($verbose);
108         unless (open(S, $src)) {
109                 print "$src: $!\n";
110                 return (0);
111         }
112         while (<S>) {
113                 chomp;
114                 tr /\015//d;
115                 push(@output, $_);
116         }
117         close(S);
118         open(D, ">$dst") or return;
119         for $_ (@output) {
120                 print D "$_\n";
121         }
122         close(D);
123         chmod(0755, $dst);
124         return (1);
125 }
126
127 sub bunzip2untar ($$) {
128         my ($file, $dir) = @_;
129
130         print "Unpacking $file into $dir\n" if ($verbose);
131         system("bunzip2 < $file | (cd $dir; tar xf -)");
132 }
133
134 $testing = $< != 0;
135 $verbose = 1;
136 $format = '';
137 $imagefile = '';
138 GetOptions('output=s' => \$output,
139         'nonet!' => \$nonet,
140         'localtime=s' => \$localtime,
141         'format=s' => \$format,
142         'ffw29!' => \$ffw29,
143         'ffw30!' => \$ffw29,
144         'i=s' => \$imagefile);
145 if (defined($output) and $output !~ m(^/)) {
146         my $d = `pwd`;
147         chomp($d);
148         $output = "$d/$output";
149 }
150 if ($imagefile) {
151         $imagefile = "-i $imagefile";
152 }
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:';
158 print <<EOF;
159 This program requires mtools, tar, bzip2, loopback mount in the kernel,
160 and root privileges to execute. Hope you have them.
161 EOF
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 '';
167 print "$append\n";
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";
175 chdir($tempdir);
176 &gunzip('initrd.gz') == 0 or die "Gunzip of initrd.gz failed\n";
177 if ($ffw29) {
178         extendinitrd("initrd", 5760);
179         system("mv newinitrd initrd");
180 }
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");
186 }
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);
190 }
191 for my $i (glob('packages/*.ini')) {
192         my $file = $i;
193         $file =~ s:packages/::;
194         &dostounix($i, "etc/$file");
195 }
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/");
207 }
208 # If a timezone file has been specified, copy that onto initrd
209 if (defined($localtime)) {
210         if (-r $localtime) {
211                 print "Copying $localtime to $tempmount/etc/localtime\n";
212                 system("cp -p $localtime $tempmount/etc/localtime");
213         } else {
214                 print "$localtime: $!\n";
215         }
216 }
217 &loopbackumount($tempmount) == 0 or die "Loopback umount failed\n";
218 &gzip('initrd') == 0 or die "Gzip of initrd failed\n";
219 if ($nonet) {
220         print "Floppyfw directory in $tempdir\n";
221 } else {
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");
226 }