Adding upstream version 4.00~pre61+dfsg.
[syslinux-debian/hramrach.git] / utils / isohybrid.pl
blob051a0bf06d7fa3ce93f95da3a4b3e84f0084b654
1 #!/usr/bin/perl
2 ## -----------------------------------------------------------------------
3 ##
4 ## Copyright 2002-2008 H. Peter Anvin - All Rights Reserved
5 ## Copyright 2009 Intel Corporation; author: H. Peter Anvin
6 ##
7 ## This program is free software; you can redistribute it and/or modify
8 ## it under the terms of the GNU General Public License as published by
9 ## the Free Software Foundation, Inc., 53 Temple Place Ste 330,
10 ## Boston MA 02111-1307, USA; either version 2 of the License, or
11 ## (at your option) any later version; incorporated herein by reference.
13 ## -----------------------------------------------------------------------
16 # Post-process an ISO 9660 image generated with mkisofs/genisoimage
17 # to allow "hybrid booting" as a CD-ROM or as a hard disk.
20 use bytes;
21 use Fcntl;
23 # User-specifyable options
24 %opt = (
25 # Fake geometry (zipdrive-style...)
26 'h' => 64,
27 's' => 32,
28 # Partition number
29 'entry' => 1,
30 # Partition offset
31 'offset' => 0,
32 # Partition type
33 'type' => 0x17, # "Windows hidden IFS"
34 # MBR ID
35 'id' => undef,
38 %valid_range = (
39 'h' => [1, 256],
40 's' => [1, 63],
41 'entry' => [1, 4],
42 'offset' => [0, 64],
43 'type' => [0, 255],
44 'id' => [0, 0xffffffff],
45 'hd0' => [0, 2],
46 'partok' => [0, 1],
49 # Boolean options just set other options
50 %bool_opt = (
51 'nohd0' => ['hd0', 0],
52 'forcehd0' => ['hd0', 1],
53 'ctrlhd0' => ['hd0', 2],
54 'nopartok' => ['partok', 0],
55 'partok' => ['partok', 1],
58 sub usage() {
59 print STDERR "Usage: $0 [options] filename.iso\n",
60 "Options:\n",
61 " -h Number of default geometry heads\n",
62 " -s Number of default geometry sectors\n",
63 " -entry Specify partition entry number (1-4)\n",
64 " -offset Specify partition offset (default 0)\n",
65 " -type Specify partition type (default 0x17)\n",
66 " -id Specify MBR ID (default random)\n",
67 " -forcehd0 Always assume we are loaded as disk ID 0\n",
68 " -ctrlhd0 Assume disk ID 0 if the Ctrl key is pressed\n",
69 " -partok Allow booting from within a partition\n";
70 exit 1;
73 # Parse a C-style integer (decimal/octal/hex)
74 sub doh($) {
75 my($n) = @_;
76 return ($n =~ /^0/) ? oct $n : $n+0;
79 sub get_random() {
80 # Get a 32-bit random number
81 my $rfd, $rnd;
82 my $rid;
84 if (open($rfd, "< /dev/urandom\0") && read($rfd, $rnd, 4) == 4) {
85 $rid = unpack("V", $rnd);
88 close($rfd) if (defined($rfd));
89 return $rid if (defined($rid));
91 # This sucks but is better than nothing...
92 return ($$+time()) & 0xffffffff;
95 sub get_hex_data() {
96 my $mbr = '';
97 my $line, $byte;
98 while ( $line = <DATA> ) {
99 chomp $line;
100 last if ($line eq '*');
101 foreach $byte ( split(/\s+/, $line) ) {
102 $mbr .= chr(hex($byte));
105 return $mbr;
108 while ($ARGV[0] =~ /^\-(.*)$/) {
109 $o = $1;
110 shift @ARGV;
111 if (defined($bool_opt{$o})) {
112 ($o, $v) = @{$bool_opt{$o}};
113 $opt{$o} = $v;
114 } elsif (exists($opt{$o})) {
115 $opt{$o} = doh(shift @ARGV);
116 if (defined($valid_range{$o})) {
117 ($l, $h) = @{$valid_range{$o}};
118 if ($opt{$o} < $l || $opt{$o} > $h) {
119 die "$0: valid values for the -$o parameter are $l to $h\n";
122 } else {
123 usage();
127 ($file) = @ARGV;
129 if (!defined($file)) {
130 usage();
133 open(FILE, "+< $file\0") or die "$0: cannot open $file: $!\n";
134 binmode FILE;
137 # First, actually figure out where mkisofs hid isolinux.bin
139 seek(FILE, 17*2048, SEEK_SET) or die "$0: $file: $!\n";
140 read(FILE, $boot_record, 2048) == 2048 or die "$0: $file: read error\n";
141 ($br_sign, $br_cat_offset) = unpack("a71V", $boot_record);
142 if ($br_sign ne ("\0CD001\1EL TORITO SPECIFICATION" . ("\0" x 41))) {
143 die "$0: $file: no boot record found\n";
145 seek(FILE, $br_cat_offset*2048, SEEK_SET) or die "$0: $file: $!\n";
146 read(FILE, $boot_cat, 2048) == 2048 or die "$0: $file: read error\n";
148 # We must have a Validation Entry followed by a Default Entry...
149 # no fanciness allowed for the Hybrid mode [XXX: might relax this later]
150 @ve = unpack("v16", $boot_cat);
151 $cs = 0;
152 for ($i = 0; $i < 16; $i++) {
153 $cs += $ve[$i];
155 if ($ve[0] != 0x0001 || $ve[15] != 0xaa55 || $cs & 0xffff) {
156 die "$0: $file: invalid boot catalog\n";
158 ($de_boot, $de_media, $de_seg, $de_sys, $de_mbz1, $de_count,
159 $de_lba, $de_mbz2) = unpack("CCvCCvVv", substr($boot_cat, 32, 32));
160 if ($de_boot != 0x88 || $de_media != 0 ||
161 ($de_segment != 0 && $de_segment != 0x7c0) || $de_count != 4) {
162 die "$0: $file: unexpected boot catalog parameters\n";
165 # Now $de_lba should contain the CD sector number for isolinux.bin
166 seek(FILE, $de_lba*2048+0x40, SEEK_SET) or die "$0: $file: $!\n";
167 read(FILE, $ibsig, 4);
168 if ($ibsig ne "\xfb\xc0\x78\x70") {
169 die "$0: $file: bootloader does not have a isolinux.bin hybrid signature.".
170 "Note that isolinux-debug.bin does not support hybrid booting.\n";
173 # Get the total size of the image
174 (@imgstat = stat(FILE)) or die "$0: $file: $!\n";
175 $imgsize = $imgstat[7];
176 if (!$imgsize) {
177 die "$0: $file: cannot determine length of file\n";
179 # Target image size: round up to a multiple of $h*$s*512
180 $h = $opt{'h'};
181 $s = $opt{'s'};
182 $cylsize = $h*$s*512;
183 $frac = $imgsize % $cylsize;
184 $padding = ($frac > 0) ? $cylsize - $frac : 0;
185 $imgsize += $padding;
186 $c = int($imgsize/$cylsize);
187 if ($c > 1024) {
188 print STDERR "Warning: more than 1024 cylinders ($c).\n";
189 print STDERR "Not all BIOSes will be able to boot this device.\n";
190 $cc = 1024;
191 } else {
192 $cc = $c;
195 # Preserve id when run again
196 if (defined($opt{'id'})) {
197 $id = pack("V", doh($opt{'id'}));
198 } else {
199 seek(FILE, 440, SEEK_SET) or die "$0: $file: $!\n";
200 read(FILE, $id, 4);
201 if ($id eq "\x00\x00\x00\x00") {
202 $id = pack("V", get_random());
206 # Print the MBR and partition table
207 seek(FILE, 0, SEEK_SET) or die "$0: $file: $!\n";
209 for ($i = 0; $i <= $opt{'hd0'}+3*$opt{'partok'}; $i++) {
210 $mbr = get_hex_data();
212 if ( length($mbr) > 432 ) {
213 die "$0: Bad MBR code\n";
216 $mbr .= "\0" x (432 - length($mbr));
218 $mbr .= pack("VV", $de_lba*4, 0); # Offset 432: LBA of isolinux.bin
219 $mbr .= $id; # Offset 440: MBR ID
220 $mbr .= "\0\0"; # Offset 446: actual partition table
222 # Print partition table
223 $offset = $opt{'offset'};
224 $psize = $c*$h*$s - $offset;
225 $bhead = int($offset/$s) % $h;
226 $bsect = ($offset % $s) + 1;
227 $bcyl = int($offset/($h*$s));
228 $bsect += ($bcyl & 0x300) >> 2;
229 $bcyl &= 0xff;
230 $ehead = $h-1;
231 $esect = $s + ((($cc-1) & 0x300) >> 2);
232 $ecyl = ($cc-1) & 0xff;
233 $fstype = $opt{'type'}; # Partition type
234 $pentry = $opt{'entry'}; # Partition slot
236 for ( $i = 1 ; $i <= 4 ; $i++ ) {
237 if ( $i == $pentry ) {
238 $mbr .= pack("CCCCCCCCVV", 0x80, $bhead, $bsect, $bcyl, $fstype,
239 $ehead, $esect, $ecyl, $offset, $psize);
240 } else {
241 $mbr .= "\0" x 16;
244 $mbr .= "\x55\xaa";
246 print FILE $mbr;
248 # Pad the image to a fake cylinder boundary
249 seek(FILE, $imgstat[7], SEEK_SET) or die "$0: $file: $!\n";
250 if ($padding) {
251 print FILE "\0" x $padding;
254 # Done...
255 close(FILE);
257 exit 0;
258 __END__
259 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 66 53 66 51 6 57 8e dd 8e c5
260 52 be 0 7c bf 0 6 b9 0 1 f3 a5 ea 2b 6 0 0 52 b4 41 bb aa 55 31 c9 30 f6 f9
261 cd 13 72 16 81 fb 55 aa 75 10 83 e1 1 74 b 66 c7 6 d1 6 b4 42 eb 15 eb 0 5a
262 51 b4 8 cd 13 83 e1 3f 5b 51 f b6 c6 40 50 f7 e1 53 52 50 bb 0 7c b9 4 0 66
263 a1 b0 7 e8 44 0 f 82 80 0 66 40 80 c7 2 e2 f2 66 81 3e 40 7c fb c0 78 70 75
264 9 fa bc ec 7b ea 44 7c 0 0 e8 83 0 69 73 6f 6c 69 6e 75 78 2e 62 69 6e 20
265 6d 69 73 73 69 6e 67 20 6f 72 20 63 6f 72 72 75 70 74 2e d a 66 60 66 31 d2
266 66 3 6 f8 7b 66 13 16 fc 7b 66 52 66 50 6 53 6a 1 6a 10 89 e6 66 f7 36 e8
267 7b c0 e4 6 88 e1 88 c5 92 f6 36 ee 7b 88 c6 8 e1 41 b8 1 2 8a 16 f2 7b cd
268 13 8d 64 10 66 61 c3 e8 1e 0 4f 70 65 72 61 74 69 6e 67 20 73 79 73 74 65
269 6d 20 6c 6f 61 64 20 65 72 72 6f 72 2e d a 5e ac b4 e 8a 3e 62 4 b3 7 cd 10
270 3c a 75 f1 cd 18 f4 eb fd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
271 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
272 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
275 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 66 53 66 51 6 57 8e dd 8e c5
276 b2 80 52 be 0 7c bf 0 6 b9 0 1 f3 a5 ea 2d 6 0 0 52 b4 41 bb aa 55 31 c9 30
277 f6 f9 cd 13 72 16 81 fb 55 aa 75 10 83 e1 1 74 b 66 c7 6 d3 6 b4 42 eb 15
278 eb 0 5a 51 b4 8 cd 13 83 e1 3f 5b 51 f b6 c6 40 50 f7 e1 53 52 50 bb 0 7c
279 b9 4 0 66 a1 b0 7 e8 44 0 f 82 80 0 66 40 80 c7 2 e2 f2 66 81 3e 40 7c fb
280 c0 78 70 75 9 fa bc ec 7b ea 44 7c 0 0 e8 83 0 69 73 6f 6c 69 6e 75 78 2e
281 62 69 6e 20 6d 69 73 73 69 6e 67 20 6f 72 20 63 6f 72 72 75 70 74 2e d a 66
282 60 66 31 d2 66 3 6 f8 7b 66 13 16 fc 7b 66 52 66 50 6 53 6a 1 6a 10 89 e6
283 66 f7 36 e8 7b c0 e4 6 88 e1 88 c5 92 f6 36 ee 7b 88 c6 8 e1 41 b8 1 2 8a
284 16 f2 7b cd 13 8d 64 10 66 61 c3 e8 1e 0 4f 70 65 72 61 74 69 6e 67 20 73
285 79 73 74 65 6d 20 6c 6f 61 64 20 65 72 72 6f 72 2e d a 5e ac b4 e 8a 3e 62
286 4 b3 7 cd 10 3c a 75 f1 cd 18 f4 eb fd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
287 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
289 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
292 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 66 53 66 51 6 57 8e dd 8e c5
293 f6 6 17 4 4 74 2 b2 80 52 be 0 7c bf 0 6 b9 0 1 f3 a5 ea 34 6 0 0 52 b4 41
294 bb aa 55 31 c9 30 f6 f9 cd 13 72 16 81 fb 55 aa 75 10 83 e1 1 74 b 66 c7 6
295 da 6 b4 42 eb 15 eb 0 5a 51 b4 8 cd 13 83 e1 3f 5b 51 f b6 c6 40 50 f7 e1
296 53 52 50 bb 0 7c b9 4 0 66 a1 b0 7 e8 44 0 f 82 80 0 66 40 80 c7 2 e2 f2 66
297 81 3e 40 7c fb c0 78 70 75 9 fa bc ec 7b ea 44 7c 0 0 e8 83 0 69 73 6f 6c
298 69 6e 75 78 2e 62 69 6e 20 6d 69 73 73 69 6e 67 20 6f 72 20 63 6f 72 72 75
299 70 74 2e d a 66 60 66 31 d2 66 3 6 f8 7b 66 13 16 fc 7b 66 52 66 50 6 53 6a
300 1 6a 10 89 e6 66 f7 36 e8 7b c0 e4 6 88 e1 88 c5 92 f6 36 ee 7b 88 c6 8 e1
301 41 b8 1 2 8a 16 f2 7b cd 13 8d 64 10 66 61 c3 e8 1e 0 4f 70 65 72 61 74 69
302 6e 67 20 73 79 73 74 65 6d 20 6c 6f 61 64 20 65 72 72 6f 72 2e d a 5e ac b4
303 e 8a 3e 62 4 b3 7 cd 10 3c a 75 f1 cd 18 f4 eb fd 0 0 0 0 0 0 0 0 0 0 0 0
304 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
305 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
306 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
308 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 21 f6 74 21 f6 4 7f 75 1c 66
309 3d 21 47 50 58 75 10 80 7c 4 ee 75 a 66 8b 4c 30 66 8b 5c 34 eb 4 66 8b 4c
310 8 66 53 66 51 6 57 8e dd 8e c5 52 be 0 7c bf 0 6 b9 0 1 f3 a5 ea 50 6 0 0
311 52 b4 41 bb aa 55 31 c9 30 f6 f9 cd 13 72 16 81 fb 55 aa 75 10 83 e1 1 74
312 b 66 c7 6 f6 6 b4 42 eb 15 eb 0 5a 51 b4 8 cd 13 83 e1 3f 5b 51 f b6 c6 40
313 50 f7 e1 53 52 50 bb 0 7c b9 4 0 66 a1 b0 7 e8 44 0 f 82 80 0 66 40 80 c7
314 2 e2 f2 66 81 3e 40 7c fb c0 78 70 75 9 fa bc ec 7b ea 44 7c 0 0 e8 83 0 69
315 73 6f 6c 69 6e 75 78 2e 62 69 6e 20 6d 69 73 73 69 6e 67 20 6f 72 20 63 6f
316 72 72 75 70 74 2e d a 66 60 66 31 d2 66 3 6 f8 7b 66 13 16 fc 7b 66 52 66
317 50 6 53 6a 1 6a 10 89 e6 66 f7 36 e8 7b c0 e4 6 88 e1 88 c5 92 f6 36 ee 7b
318 88 c6 8 e1 41 b8 1 2 8a 16 f2 7b cd 13 8d 64 10 66 61 c3 e8 1e 0 4f 70 65
319 72 61 74 69 6e 67 20 73 79 73 74 65 6d 20 6c 6f 61 64 20 65 72 72 6f 72 2e
320 d a 5e ac b4 e 8a 3e 62 4 b3 7 cd 10 3c a 75 f1 cd 18 f4 eb fd 0 0 0 0 0 0
321 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
322 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
323 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
325 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 21 f6 74 21 f6 4 7f 75 1c 66
326 3d 21 47 50 58 75 10 80 7c 4 ee 75 a 66 8b 4c 30 66 8b 5c 34 eb 4 66 8b 4c
327 8 66 53 66 51 6 57 8e dd 8e c5 b2 80 52 be 0 7c bf 0 6 b9 0 1 f3 a5 ea 52
328 6 0 0 52 b4 41 bb aa 55 31 c9 30 f6 f9 cd 13 72 16 81 fb 55 aa 75 10 83 e1
329 1 74 b 66 c7 6 f8 6 b4 42 eb 15 eb 0 5a 51 b4 8 cd 13 83 e1 3f 5b 51 f b6
330 c6 40 50 f7 e1 53 52 50 bb 0 7c b9 4 0 66 a1 b0 7 e8 44 0 f 82 80 0 66 40
331 80 c7 2 e2 f2 66 81 3e 40 7c fb c0 78 70 75 9 fa bc ec 7b ea 44 7c 0 0 e8
332 83 0 69 73 6f 6c 69 6e 75 78 2e 62 69 6e 20 6d 69 73 73 69 6e 67 20 6f 72
333 20 63 6f 72 72 75 70 74 2e d a 66 60 66 31 d2 66 3 6 f8 7b 66 13 16 fc 7b
334 66 52 66 50 6 53 6a 1 6a 10 89 e6 66 f7 36 e8 7b c0 e4 6 88 e1 88 c5 92 f6
335 36 ee 7b 88 c6 8 e1 41 b8 1 2 8a 16 f2 7b cd 13 8d 64 10 66 61 c3 e8 1e 0
336 4f 70 65 72 61 74 69 6e 67 20 73 79 73 74 65 6d 20 6c 6f 61 64 20 65 72 72
337 6f 72 2e d a 5e ac b4 e 8a 3e 62 4 b3 7 cd 10 3c a 75 f1 cd 18 f4 eb fd 0
338 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
339 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
340 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
342 fa 31 ed 8e d5 bc 0 7c fb fc 66 31 db 66 31 c9 21 f6 74 21 f6 4 7f 75 1c 66
343 3d 21 47 50 58 75 10 80 7c 4 ee 75 a 66 8b 4c 30 66 8b 5c 34 eb 4 66 8b 4c
344 8 66 53 66 51 6 57 8e dd 8e c5 f6 6 17 4 4 74 2 b2 80 52 be 0 7c bf 0 6 b9
345 0 1 f3 a5 ea 59 6 0 0 52 b4 41 bb aa 55 31 c9 30 f6 f9 cd 13 72 16 81 fb 55
346 aa 75 10 83 e1 1 74 b 66 c7 6 ff 6 b4 42 eb 15 eb 0 5a 51 b4 8 cd 13 83 e1
347 3f 5b 51 f b6 c6 40 50 f7 e1 53 52 50 bb 0 7c b9 4 0 66 a1 b0 7 e8 44 0 f
348 82 80 0 66 40 80 c7 2 e2 f2 66 81 3e 40 7c fb c0 78 70 75 9 fa bc ec 7b ea
349 44 7c 0 0 e8 83 0 69 73 6f 6c 69 6e 75 78 2e 62 69 6e 20 6d 69 73 73 69 6e
350 67 20 6f 72 20 63 6f 72 72 75 70 74 2e d a 66 60 66 31 d2 66 3 6 f8 7b 66
351 13 16 fc 7b 66 52 66 50 6 53 6a 1 6a 10 89 e6 66 f7 36 e8 7b c0 e4 6 88 e1
352 88 c5 92 f6 36 ee 7b 88 c6 8 e1 41 b8 1 2 8a 16 f2 7b cd 13 8d 64 10 66 61
353 c3 e8 1e 0 4f 70 65 72 61 74 69 6e 67 20 73 79 73 74 65 6d 20 6c 6f 61 64
354 20 65 72 72 6f 72 2e d a 5e ac b4 e 8a 3e 62 4 b3 7 cd 10 3c a 75 f1 cd 18
355 f4 eb fd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
357 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0