#! /usr/bin/perl # relocate boot catalog # # Copyright (c) 2007 Steffen Winterfeldt # # License GPLv3+: GNU GPL version 3 or later # This is free software: you are free to change and redistribute it. # # # mkisofs/genisoimage leave one sector empty (or fill it with version info # if the ISODEBUG environment variable is set) before starting the path # table. # # We use this space to move the boot catalog there. # # usage: # # relocate_catalog cd_image.iso # sub read_sector; sub write_sector; $iso = shift; die "$iso: $!\n" unless open ISO, "+<$iso"; $vol_descr = read_sector 0x10; $vol_id = substr($vol_descr, 0, 7); die "$iso: no iso9660 fs\n" if $vol_id ne "\x01CD001\x01"; $path_table = unpack "V", substr($vol_descr, 0x08c, 4); die "$iso: strange path table location: $path_table\n" if $path_table < 0x11; $new_location = $path_table - 1; $eltorito_descr = read_sector 0x11; $eltorito_id = substr($eltorito_descr, 0, 0x1e); die "$iso: not bootable\n" if $eltorito_id ne "\x00CD001\x01EL TORITO SPECIFICATION"; $boot_catalog = unpack "V", substr($eltorito_descr, 0x47, 4); die "$iso: strange boot catalog location: $boot_catalog\n" if $boot_catalog < 0x12; $vol_descr2 = read_sector $new_location - 1; $vol_id2 = substr($vol_descr2, 0, 7); if($vol_id2 ne "\xffCD001\x01") { undef $new_location; for($i = 0x12; $i < 0x40; $i++) { $vol_descr2 = read_sector $i; $vol_id2 = substr($vol_descr2, 0, 7); if($vol_id2 eq "\x00TEA01\x01" || $boot_catalog == $i + 1) { $new_location = $i + 1; last; } } } die "$iso: unexpected layout\n" unless defined $new_location; if($boot_catalog == $new_location) { print "boot catalog already relocated\n"; exit 0; } $version_descr = read_sector $new_location; die "$iso: unexpected layout\n" if $version_descr ne ("\x00" x 0x800) && substr($version_descr, 0, 4) ne "MKI "; $boot_catalog_data = read_sector $boot_catalog; # now reloacte to $new_location substr($eltorito_descr, 0x47, 4) = pack "V", $new_location; write_sector $new_location, $boot_catalog_data; write_sector 0x11, $eltorito_descr; printf "boot catalog relocated: %d -> %d\n", $boot_catalog, $new_location; close ISO; sub read_sector { my $buf; die "$iso: seek error!\n" unless seek ISO, $_[0] * 0x800, 0; die "$iso: read error\n" if sysread(ISO, $buf, 0x800) != 0x800; return $buf; } sub write_sector { die "$iso: seek error!\n" unless seek ISO, $_[0] * 0x800, 0; die "$iso: write error\n" if syswrite(ISO, $_[1], 0x800) != 0x800; }