livecd-tools/rosa-image-fix-x86.pl

47 lines
1.6 KiB
Perl
Raw Permalink Normal View History

#!/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);