mkffwnb.pl 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. use Getopt::Long;
  25. use lib '/usr/local/lib/mkffwnb/';
  26. use Extendinitrd;
  27. use strict;
  28. use vars qw($testing $verbose $localtime $nonet $format $ffw29 $imagefile
  29. $floppy $libdir $tftpdir $output $tempdir $tempmount);
  30. sub findversion () {
  31. my ($version) = grep(/FloppyFW/, `mtype $imagefile ${floppy}floppyfw.msg`);
  32. return '' unless defined($version) and $version ne '';
  33. chomp($version);
  34. $version =~ s/.*FloppyFW (\d+\.\d+\.\d+(\.\d+)?).*/$1/;
  35. return ($version);
  36. }
  37. sub getappendargs () {
  38. my ($append) = join(' ', grep(/^\s*(append\s|console=)/, `mtype $imagefile ${floppy}syslinux.cfg`));
  39. chomp ($append);
  40. my @args = split(/\s+/, $append);
  41. my @result = ();
  42. foreach $_ (@args) {
  43. next if (/^$/ or /^append/ or /^initrd=/);
  44. next if (!$ffw29 and /^root=/);
  45. push (@result, $_);
  46. }
  47. return (join(' ', @result));
  48. }
  49. # Copy whole floppy to the current directory
  50. # m preserves timestamps, n overwrites without warning and / means recursive
  51. sub mcopy ($) {
  52. my ($tempdir) = @_;
  53. print "mcopy $imagefile -mn/ ${floppy}* $tempdir\n";
  54. my $status = system("mcopy -mn/ $imagefile ${floppy}* $tempdir");
  55. return ($status / 256);
  56. }
  57. # Gunzip file, -f forces overwriting of uncompressed file
  58. sub gunzip ($) {
  59. my ($file) = @_;
  60. print "Gunzipping $file\n" if ($verbose);
  61. my $status = system('gunzip', '-f', $file);
  62. return ($status / 256);
  63. }
  64. # Gzip file, -f forces overwriting of compressed file
  65. sub gzip ($) {
  66. my ($file) = @_;
  67. print "Gzipping $file\n" if ($verbose);
  68. my $status = system('gzip', '-9', '-f', $file);
  69. return ($status / 256);
  70. }
  71. sub loopbackmount ($$) {
  72. my ($file, $point) = @_;
  73. print "Mounting $file on $point loopback\n" if ($verbose);
  74. my $status = system('mount', '-o', 'loop', $file, $point);
  75. return ($testing ? 0 : $status / 256);
  76. }
  77. sub loopbackumount ($) {
  78. my ($point) = @_;
  79. print "Umounting $point\n" if ($verbose);
  80. my $status = system('umount', $point);
  81. return ($testing ? 0 : $status / 256);
  82. }
  83. # Convert DOS CR-NL to Unix NL. $dst has implied prefix of $tempmount
  84. # Use @output for temporary storage in case we write back to the same file
  85. sub dostounix ($$) {
  86. my ($src, $dst) = @_;
  87. my @output = ();
  88. $dst = "$tempmount/$dst";
  89. print "Converting $src to $dst\n" if ($verbose);
  90. unless (open(S, $src)) {
  91. print "$src: $!\n";
  92. return (0);
  93. }
  94. while (<S>) {
  95. chomp;
  96. tr /\015//d;
  97. push(@output, $_);
  98. }
  99. close(S);
  100. open(D, ">$dst") or return;
  101. for $_ (@output) {
  102. print D "$_\n";
  103. }
  104. close(D);
  105. chmod(0755, $dst);
  106. return (1);
  107. }
  108. sub bunzip2untar ($$) {
  109. my ($file, $dir) = @_;
  110. print "Unpacking $file into $dir\n" if ($verbose);
  111. system("bunzip2 < $file | (cd $dir; tar xf -)");
  112. }
  113. $testing = $< != 0;
  114. $verbose = 1;
  115. $format = '';
  116. $imagefile = '';
  117. GetOptions('output=s' => \$output,
  118. 'nonet!' => \$nonet,
  119. 'localtime=s' => \$localtime,
  120. 'format=s' => \$format,
  121. 'ffw29!' => \$ffw29,
  122. 'ffw30!' => \$ffw29,
  123. 'i=s' => \$imagefile);
  124. if (defined($output) and $output !~ m(^/)) {
  125. my $d = `pwd`;
  126. chomp($d);
  127. $output = "$d/$output";
  128. }
  129. if ($imagefile) {
  130. $imagefile = "-i $imagefile";
  131. }
  132. $libdir = '/usr/local/lib/mkffwnb';
  133. $tftpdir = '/usr/local/var/tftpboot';
  134. # default can also be 'elf'
  135. $format = 'nbi' if ($format ne 'elf' and $format ne 'nbi');
  136. $floppy = $#ARGV >= 0 ? $ARGV[0] : 'a:';
  137. print <<EOF;
  138. This program requires mtools, tar, bzip2, loopback mount in the kernel,
  139. and root privileges to execute. Hope you have them.
  140. EOF
  141. my $version = &findversion();
  142. $version ne '' or die "Cannot determine version\n";
  143. print "Version $version\n";
  144. my $append = &getappendargs();
  145. $append = "--append='$append'" if $append ne '';
  146. print "$append\n";
  147. $libdir .= '/' . $version;
  148. -d $libdir or die "Cannot find files for $version\n";
  149. $tempdir = $nonet ? '/tmp/mkffwnb' : "/tmp/mkffwnb$$";
  150. $tempmount = 'tmpmount';
  151. mkdir($tempdir, 0755);
  152. print "Copying files off floppy, please be patient...\n";
  153. &mcopy($tempdir) == 0 or die "Mcopy failed, diskette problem?\n";
  154. chdir($tempdir);
  155. &gunzip('initrd.gz') == 0 or die "Gunzip of initrd.gz failed\n";
  156. if ($ffw29) {
  157. extendinitrd("initrd", 5760);
  158. system("mv newinitrd initrd");
  159. }
  160. mkdir($tempmount, 0755);
  161. &loopbackmount('initrd', $tempmount) == 0 or die "Loopback mount failed\n";
  162. &dostounix("$libdir/linuxrc", "linuxrc") if (-r "$libdir/linuxrc");
  163. unless (&dostounix("$libdir/floppyfw.ini", "floppyfw.ini")) {
  164. &dostounix("floppyfw/floppyfw.ini", $ffw29 ? "etc/floppyfw.ini" : "floppyfw.ini");
  165. }
  166. &dostounix("config", $ffw29 ? "etc/config.prelogin" : "etc/config");
  167. for my $i (glob('*.bz2 floppyfw/add.bz2 modules/*.bz2 packages/*.bz2')) {
  168. &bunzip2untar($i, $tempmount);
  169. }
  170. for my $i (glob('packages/*.ini')) {
  171. my $file = $i;
  172. $file =~ s:packages/::;
  173. &dostounix($i, "etc/$file");
  174. }
  175. &dostounix("hosts", "etc/hosts");
  176. &dostounix("modules.lst", "etc/modules.lst");
  177. &dostounix("network.ini", "etc/network.init");
  178. &dostounix("firewall.ini", "etc/firewall.init");
  179. &dostounix("syslog.cfg", "etc/syslog.conf");
  180. &dostounix("packages/timeinfo", "etc/localtime");
  181. system("cp -p licenses/* $tempmount/licenses/");
  182. # This conditional code is for 1.1.2 and below
  183. unless (glob('modules/*.bz2')) {
  184. print "Copying additional modules\n" if ($verbose);
  185. system("cp -p modules/* $tempmount/lib/modules/");
  186. }
  187. # If a timezone file has been specified, copy that onto initrd
  188. if (defined($localtime)) {
  189. if (-r $localtime) {
  190. print "Copying $localtime to $tempmount/etc/localtime\n";
  191. system("cp -p $localtime $tempmount/etc/localtime");
  192. } else {
  193. print "$localtime: $!\n";
  194. }
  195. }
  196. &loopbackumount($tempmount) == 0 or die "Loopback umount failed\n";
  197. &gzip('initrd') == 0 or die "Gzip of initrd failed\n";
  198. if ($nonet) {
  199. print "Floppyfw directory in $tempdir\n";
  200. } else {
  201. print "Calling mk$format-linux to make the netbootable image\n" if ($verbose);
  202. $output = "$tftpdir/floppyfw-$version.nb" if (!defined($output));
  203. system("mk$format-linux $append --output=$output vmlinuz initrd.gz");
  204. system("rm -fr $tempdir");
  205. }