Skip to content

Instantly share code, notes, and snippets.

@Zrubi
Created April 6, 2017 13:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zrubi/56a43cc610c48300fcb4e9249ab47776 to your computer and use it in GitHub Desktop.
Save Zrubi/56a43cc610c48300fcb4e9249ab47776 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Std;
# geteltorito.pl: a bootimage extractor
# Script that will extract the first El Torito bootimage from a
# bootable CD image
#
# Credits:
# R. Krienke 08/2001
# krienke@uni-koblenz.de
# License: GPL
#
# Get the original version from:
# http://userpages.uni-koblenz.de/~krienke/ftp/noarch/geteltorito
my $utilVersion="1.0";
# For information on El Torito see
# http://en.wikipedia.org/wiki/El_torito
my $vSecSize=512;
my $secSize=2048;
my ($sector, $cnt, $counter);
#
# Read a particular sector from a file
# sector counting starts at 0, not 1
#
sub getSector{
my ($secNum, $secCount, $file)=@_;
my ($sec, $count);
open(FILE, "<:raw", $file) || die "Cannot open \"$file\" \n";
seek(FILE, $secNum*$secSize, 0);
$count=read(FILE, $sec, $vSecSize*$secCount, 0) ;
if( $count != $vSecSize*$secCount ){
warn "Error reading from file \"$file\"\n";
}
close(FILE);
return($sec);
}
# ---------------------------------------------------------------------
my $imageFile=$ARGV[0];
if( ! -r $imageFile ){
die "Cannot read image/device \"$imageFile\". Aborting\n";
}
#
# Read Sector 17 from CD which should contain a Boot Record Volume
# descriptor. This descriptor contains at its start the text ($isoIdent)
# CD001 and ($toritoSpec)
# EL TORITO SPECIFICATION
# see http://www.cdpage.com/Compact_Disc_Variations/eltoritoi.html
# for details
#
my ($boot, $isoIdent, $version, $toritoSpec,
$unUsed, $bootP);
my ($media, $loadSegment, $systemType, $sCount, $imgStart);
my ($header, $platform, $manufact, $five, $aa);
$sector=getSector(17, 1, $imageFile );
($boot, $isoIdent, $version, $toritoSpec,
$unUsed, $bootP)= unpack( "Ca5CA32A32V", $sector );
if( $isoIdent ne "CD001" || $toritoSpec ne "EL TORITO SPECIFICATION" ){
die "This data image does not seem to be a bootable CD-image\n";
}
#
# Now fetch the sector of the booting catalog
#
$sector=getSector($bootP, 1, $imageFile );
print STDERR "Booting catalog starts at sector: $bootP \n";
# The first 32 bytes of this sector contains the validation entry for a
# boot. The first byte has to be 01, the next byte determines the
# architecture the image is designed for, where 00 is i86, 01 is PowerPC
# and 02 is Mac. More data give info about manufacturer, etc. The
# final two bytes must contain 0x55 and 0xAA respectively (as
# defined by the El Torito standard).
my $validateEntry=substr($sector, 0, 32);
($header, $platform, $unUsed, $manufact, $unUsed, $five, $aa)=
unpack( "CCvA24vCC", $validateEntry);
if( $header != 1 || $five != 0x55 || $aa != 0xaa ){
die "Invalid Validation Entry on image \n";
}
print STDERR "Manufacturer of CD: $manufact\n";
print STDERR "Image architecture: ";
print STDERR "x86" if( $platform == 0 );
print STDERR "PowerPC" if( $platform == 1 );
print STDERR "Mac" if( $platform == 2 );
print STDERR "unknown ($platform)" if( $platform > 2 );
print STDERR "\n";
#
# Now we examine the initial/defaultentry which follows the validate
# entry and has a size of 32 bytes.
my $initialEntry=substr($sector, 32, 32);
($boot, $media, $loadSegment, $systemType, $unUsed,
$sCount, $imgStart, $unUsed)=unpack( "CCvCCvVC", $initialEntry);
if( $boot != 0x88 ){
die "Boot indicator in Initial/Default-Entry is not 0x88. CD is not bootable. \n";
}
print STDERR "Boot media type is: ";
if( $media == 0 ){
print STDERR "no emulation";
$counter=0;
}
if( $media == 1 ){
print STDERR "1.2meg floppy";
$counter=1200*1024/$vSecSize;
}
if( $media == 2 ){
print STDERR "1.44meg floppy";
$counter=1440*1024/$vSecSize;
}
if( $media == 3 ){
print STDERR "2.88meg floppy";
$counter=2880*1024/$vSecSize;
}
if( $media == 4 ){
print STDERR "harddisk";
my $MBR=getSector($imgStart, 1, $imageFile );
my $partition1=substr($MBR, 446, 16);
my ($unUsed, $firstSector, $partitionSize) = unpack( "A8VV", $partition1);
$counter=$firstSector + $partitionSize;
}
print STDERR "\n";
# Only use the internal sector counter if the real size is unknown
# ($count==0)
$cnt=$counter==0?$sCount:$counter;
print STDERR "El Torito image starts at sector $imgStart and has $cnt sector(s) of $vSecSize Bytes\n";
# We are there:
# Now read the bootimage to stdout
print getSector($imgStart, $cnt, $imageFile);
print STDERR "Image has been written to stdout ....\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment