#!/usr/bin/perl use strict; use warnings; use Fcntl ':seek'; if (scalar(@ARGV) < 1) { print "Usage: $0 iso-image-file\n"; exit; } my $filename = $ARGV[0]; my $file; open($file, '+<', $filename) or die "Failed to open file $filename for read-write: $!"; binmode($file); # Read the first sector (512 bytes) containing the MBR my $mbr; read($file, $mbr, 512) or die "Failed to read the MBR sector: $!"; # Extract the second partition record from the MBR (except for the "bootable" flag) my $partition2 = substr($mbr, 463, 15); # In 32-bit images we don't have the second partition (EFI), so here we'll create # a fake partition without actual file system. if ($partition2 eq ("\x00" x 15)) { # Partition recod $partition2 = "\x00\x02\x00" . # CHS: first sector = 2 "\xDA" . # partition type: non-filesystem data "\x00\x02\x00" . # CHS: last sector = 2 "\x01\x00\x00\x00" . # LBA: first sector = 1 "\x01\x00\x00\x00"; # LBA: number of sectors = 1 } # Now write back the desired partition table into MBR. # The partition table starts at offset 446 and contains 4 records 16 bytes each. What we do: # 1) Replace the first record with the second one (real or faked for 32-bit images); # 2) Replace the first byte of the resulting first record with 0x80 (mark partition as active); # 3) Delete the second partition by zeroing its contents. substr($mbr, 446, 32) = "\x80" . $partition2 . ("\x00" x 16); # Write the updated MBR back seek($file, 0, SEEK_SET) or die "Failed to position at the beginning of the file: $!"; print $file $mbr; close($file);