summaryrefslogtreecommitdiff
path: root/isohybrid-acritox
diff options
context:
space:
mode:
Diffstat (limited to 'isohybrid-acritox')
-rwxr-xr-xisohybrid-acritox150
1 files changed, 150 insertions, 0 deletions
diff --git a/isohybrid-acritox b/isohybrid-acritox
new file mode 100755
index 0000000..0d1c6f9
--- /dev/null
+++ b/isohybrid-acritox
@@ -0,0 +1,150 @@
+#!/usr/bin/perl
+# isohybrid-acritox - written by Andreas Loibl <andreas@andreas-loibl.de>
+#
+# Post-process a hybrid-ISO-image generated with isohybrid-bg2
+# by injecting an "Apple Partition Map" into the image and appending a HFS+-partiton
+# and a FAT-partition to allow "hybrid booting" as CD-ROM (EFI or El Torito) or as
+# a hard-drive on Intel-Macs (EFI) and PCs (EFI or MBR).
+
+$bs=0x0200; $block0='45520200eb5f90'; # 512 - add (%eax),%al
+$bs=0x0400; $block0='45520400eb5f90'; # 1024 - add $0x0,%al
+
+# Apple Partition Map entries:
+$pm1='504d000000000004000000010000000f4170706c650000000000000000000000000000000000000000000000000000004170706c655f706172746974696f6e5f6d617000000000000000000000000000000000000000000f00000003';
+$pm2='504d00000000000400000010000000014d6163696e746f736800000000000000000000000000000000000000000000004170706c655f4472697665725f41544150490000000000000000000000000000000000000000000100000303000000002674b000000000000000000000000000000000000000eaeb0000000000000000000000000000000049534f43';
+$pm3='504d00000000000400000400000005006469736b20696d616765000000000000000000000000000000000000000000004170706c655f4846530000000000000000000000000000000000000000000000000000000000040040000033';
+$pm4='504d000000000004000009000000001000000000000000000000000000000000000000000000000000000000000000004170706c655f4672656500000000000000000000000000000000000000000000000000000000001000000001';
+
+die "Usage: $0 <isohybrid-bg2.iso> <HFS+-image> <FAT-image>\n" if $#ARGV != 2;
+
+($file, $part, $fat) = @ARGV;
+open(FILE, "+< $file\0") or die "$0: cannot open $file: $!\n";
+binmode FILE;
+
+open(PART, "< $part\0") or die "$0: cannot open $part: $!\n";
+binmode PART;
+
+open(FAT, "< $fat\0") or die "$0: cannot open $fat: $!\n";
+binmode FAT;
+
+# Check if image has already been "patched" (i.e. it has the APM signature from $block0)
+seek(FILE, 0, SEEK_SET) or die "$0: $file: $!\n";
+read(FILE, $test, 2) == 2 or die "$0: $file: read error\n";
+die "$file seems to have an APM signature already...\n" if($test eq 'ER');
+
+# Check if image is a isohybrid-bg2 image (i.e. it has GRUB in its MBR)
+seek(FILE, 0x180, SEEK_SET) or die "$0: $file: $!\n";
+read(FILE, $test, 4) == 4 or die "$0: $file: read error\n";
+die "$file seems not to have GRUB in its MBR (is this a isohybrid-bg2 image?)\n" if($test ne 'GRUB');
+
+# Check if partition contains a HFS+ filesystem
+seek(PART, 0x400, SEEK_SET) or die "$0: $file: $!\n";
+read(PART, $test, 2) == 2 or die "$0: $file: read error\n";
+die "$part doesn't seem to contain a HFS+ filesystem\n" if($test ne 'H+');
+
+# Get the total size of the image
+(@imgstat = stat(FILE)) or die "$0: $file: $!\n";
+$imgsize = $imgstat[7];
+if (!$imgsize) {
+ die "$0: $file: cannot determine length of file\n";
+}
+# Target image size: round up to a multiple of $bs*512
+$cylsize = $bs*512;
+$frac = $imgsize % $cylsize;
+$padding = ($frac > 0) ? $cylsize - $frac : 0;
+$imgsize += $padding;
+
+# Get the total size of the partiton
+(@partstat = stat(PART)) or die "$0: $part: $!\n";
+$partsize = $partstat[7];
+if (!$partsize) {
+ die "$0: $part: cannot determine length of file\n";
+}
+
+# Get the total size of the partiton
+(@fatstat = stat(FAT)) or die "$0: $part: $!\n";
+$fatsize = $fatstat[7];
+if (!$fatsize) {
+ die "$0: $part: cannot determine length of file\n";
+}
+
+seek(FILE, 0, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('H*',$block0);
+seek(FILE, $bs*1, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('H*',$pm1);
+seek(FILE, $bs*2, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('H*',$pm2);
+seek(FILE, $bs*3, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('H*',$pm3);
+seek(FILE, $bs*4, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('H*',$pm4);
+
+# Pad the image to a fake cylinder boundary
+seek(FILE, $imgstat[7], SEEK_SET) or die "$0: $file: $!\n";
+if ($padding) {
+ print FILE "\0" x $padding;
+}
+
+# Append partition to image
+seek(PART, 0, SEEK_SET) or die "$0: $file: $!\n";
+read PART, $partition, $partsize;
+print FILE $partition;
+
+# Pad the partition to a fake cylinder boundary
+$frac = $partsize % $cylsize;
+$padding = ($frac > 0) ? $cylsize - $frac : 0;
+if ($padding) {
+ print FILE "\0" x $padding;
+}
+$partsize += $padding;
+
+# Adjust $pm3 (Apple_HFS)
+# "physical block start" and "physical block count" of partition:
+seek(FILE, $bs*3+8, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('NN', $imgsize/$bs, $partsize/$bs);
+# "logical block start" and "logical block count" of partition:
+seek(FILE, $bs*3+80, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('NN', 0, $partsize/$bs);
+# Adjust $pm4 (Apple_Free)
+# "physical block start" of partition:
+seek(FILE, $bs*4+8, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack('N', $imgsize/$bs + $partsize/$bs);
+
+$imgsize += $partsize;
+seek(FILE, $imgsize, SEEK_SET) or die "$0: $file: $!\n";
+
+# Target image size: round up to a multiple of 1MB
+$cylsize = 64*32*512; # 1MB
+$frac = $imgsize % $cylsize;
+$padding = ($frac > 0) ? $cylsize - $frac : 0;
+$imgsize += $padding;
+if ($padding) {
+ print FILE "\0" x $padding;
+}
+
+# Append FAT partition to image
+read FAT, $partition, $fatsize;
+print FILE $partition;
+
+# Pad the partition to a fake cylinder boundary
+$frac = $fatsize % $cylsize;
+$padding = ($frac > 0) ? $cylsize - $frac : 0;
+if ($padding) {
+ print FILE "\0" x $padding;
+}
+$fatsize += $padding;
+
+# Adjust MBR partition table
+$fstype = 0xEF;
+$pentry = 2;
+
+seek(FILE, 430+16*$pentry, SEEK_SET) or die "$0: $file: $!\n";
+print FILE pack("CCCCCCCCVV", 0x80, 0xfe, 0xff, 0xff, $fstype, 0xfe, 0xff, 0xff, $imgsize/512, $fatsize/512);
+
+$imgsize += $fatsize;
+
+# Done...
+close(PART);
+close(FILE);
+
+exit 0;