isohybrid: add options, change default ptype to 0x17
authorH. Peter Anvin <hpa@zytor.com>
Thu, 21 May 2009 02:06:42 +0000 (19:06 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 21 May 2009 02:07:53 +0000 (19:07 -0700)
Add support for setting a variety of options in isohybrid.  Also
change the default partition type to 0x17, "Windows hidden IFS", as
that seems to make Windows less unhappy.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
NEWS
utils/isohybrid.in

diff --git a/NEWS b/NEWS
index d753563..6518456 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Changes in 3.81:
          new "NOHALT 1" configuration command.
        * linux.c32 now suppresses all messages if the "quiet" flag is
          specified.
+       * isohybrid: add a variety of options, and a help message.
 
 Changes in 3.80:
        * New shuffler mechanism and API.
index 83f9dc0..61ff795 100644 (file)
 use bytes;
 use Fcntl;
 
-# Use this fake geometry (zipdrive-style...)
-$h = 64; $s = 32;
+# User-specifyable options
+%opt = (
+    # Fake geometry (zipdrive-style...)
+    'h'      => 64,
+    's'      => 32,
+    # Partition number
+    'entry'  => 1,
+    # Partition offset
+    'offset' => 0,
+    # Partition type
+    'type'   => 0x17,          # "Windows hidden IFS"
+    # MBR ID
+    'id'     => undef,
+);
+
+%valid_range = (
+    'h'      => [1, 256],
+    's'      => [1, 63],
+    'entry'  => [1, 4],
+    'offset' => [0, 64],
+    'type'   => [0, 255],
+    'id'     => [0, 0xffffffff],
+);
+
+sub usage() {
+    print STDERR "Usage: $0 [options] filename\n",
+    "Options:\n",
+    "  -h      Number of default geometry heads\n",
+    "  -s      Number of default geometry sectors\n",
+    "  -entry  Specify partition entry number (1-4)\n",
+    "  -offset Specify partition offset (default 0)\n",
+    "  -type   Specify partition type (default 0x17)\n",
+    "  -id     Specify MBR ID (default random)\n";
+    exit 1;
+}
+
+# Parse a C-style integer (decimal/octal/hex)
+sub doh($) {
+    my($n) = @_;
+    return ($n =~ /^0/) ? oct $n : $n+0;
+}
 
 sub get_random() {
     # Get a 32-bit random number
@@ -38,8 +77,28 @@ sub get_random() {
     return ($$+time()) & 0xffffffff;
 }
 
+while ($ARGV[0] =~ /^\-(.*)$/) {
+    $o = $1;
+    shift @ARGV;
+    if (exists($opt{$o})) {
+       $opt{$o} = doh(shift @ARGV);
+       if (defined($valid_range{$o})) {
+           ($l, $h) = @{$valid_range{$o}};
+           if ($opt{$o} < $l || $opt{$o} > $h) {
+               die "$0: valid values for the -$o parameter are $l to $h\n";
+           }
+       }
+    } else {
+       usage();
+    }
+}
 
 ($file) = @ARGV;
+
+if (!defined($file)) {
+    usage();
+}
+
 open(FILE, "+< $file\0") or die "$0: cannot open $file: $!\n";
 binmode FILE;
 
@@ -87,6 +146,8 @@ if (!$imgsize) {
     die "$0: $file: cannot determine length of file\n";
 }
 # Target image size: round up to a multiple of $h*$s*512
+$h = $opt{'h'};
+$s = $opt{'s'};
 $cylsize = $h*$s*512;
 $frac = $imgsize % $cylsize;
 $padding = ($frac > 0) ? $cylsize - $frac : 0;
@@ -101,10 +162,14 @@ if ($c > 1024) {
 }
 
 # Preserve id when run again
-seek(FILE, 440, SEEK_SET) or die "$0: $file: $!\n";
-read(FILE, $id, 4);
-if ($id eq "\x00\x00\x00\x00") {
-    $id = pack("V", get_random());
+if (defined($opt{'id'})) {
+    $id = $opt{'id'};
+} else {
+    seek(FILE, 440, SEEK_SET) or die "$0: $file: $!\n";
+    read(FILE, $id, 4);
+    if ($id eq "\x00\x00\x00\x00") {
+       $id = pack("V", get_random());
+    }
 }
 
 # Print the MBR and partition table
@@ -123,20 +188,23 @@ if ( length($mbr) > 432 ) {
 
 $mbr .= "\0" x (432 - length($mbr));
 
-$mbr .= pack("VV", $de_lba*4, 0); # Offset 432: LBA of isolinux.bin
+$mbr .= pack("VV", $de_lba*4, 0);      # Offset 432: LBA of isolinux.bin
 $mbr .= $id;                           # Offset 440: MBR ID
-$mbr .= "\0\0";                        # Offset 446: actual partition table
+$mbr .= "\0\0";                                # Offset 446: actual partition table
 
 # Print partition table
+$offset  = $opt{'offset'};
 $psize   = $c*$h*$s;
-$bhead   = 0;
-$bsect   = 1;
-$bcyl    = 0;
+$bhead   = int($offset/$s) % $h;
+$bsect   = ($offset % $s) + 1;
+$bcyl    = int($offset/($h*$s));
+$bsect  += ($bcyl & 0x300) >> 2;
+$bcyl   &= 0xff;
 $ehead   = $h-1;
 $esect   = $s + ((($cc-1) & 0x300) >> 2);
 $ecyl    = ($cc-1) & 0xff;
-$fstype  = 0x83;               # Linux (any better ideas?)
-$pentry  = 1;                  # First partition slot
+$fstype  = $opt{'type'};       # Partition type
+$pentry  = $opt{'entry'};      # Partition slot
 
 for ( $i = 1 ; $i <= 4 ; $i++ ) {
     if ( $i == $pentry ) {