Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / 3rd-party / geteltorito / geteltorito.pl
1 #!/usr/bin/perl
2
3 use Getopt::Std;
4
5 #
6 # geteltorito.pl: a bootimage extractor
7 # Script that will extract the first El Torito bootimage from a
8 # bootable CD image
9 # R. Krienke 08/2001
10 # krienke@uni-koblenz.de
11 # License: GPL
12 #
13 # Get latest version from:
14 # http://www.uni-koblenz.de/~krienke/ftp/noarch/geteltorito
15 #
16 $utilVersion="0.4"; 
17 #
18 # Version 0.4
19 #    2007/02/01
20 #    A patch from Santiago Garcia <manty@debian.org> to use a virtual sector
21 #    size (vSecSize) of 512 bytes, as defined on "El Torito" specs and change
22 #    unpack of the sector count from n to v to get the correct sector count.
23 # Version 0.3
24 #    2006/02/21
25 #    A patch from  Ben Collins <bcollins@ubuntu.com> to make the 
26 #    utility work on PPC machines (change from 'L'-encoding in pack to 'V')
27 # Version 0.2
28 #    Several patches included from Nathan Stratton Treadway(nathant@ontko.com)
29 #    to adjust the platform output as well as fixes for other minor bugs
30 # Version 0.1
31 #    Initial release
32 #
33 # For information on El Torito see 
34 # http://wikipedia.org/
35 # or try this link directly:
36 # http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/Platform+System+Software+Documents/default.htm
37
38 $vSecSize=512;
39 $secSize=2048;
40 $ret=undef;$version=undef;$opt_h=undef;$loadSegment=undef;$systemType=undef;
41
42 #
43 # Read a particular sector from a file
44 # sector counting starts at 0, not 1
45 #
46 sub getSector{
47    my ($secNum, $secCount, $file)=@_;
48    my ($sec, $count);
49
50    open(FILE, $file) || die "Cannot open \"$file\" \n";
51
52    seek(FILE, $secNum*$secSize, 0);
53    $count=read(FILE, $sec, $vSecSize*$secCount, 0) ;
54    if( $count != $vSecSize*$secCount ){
55        warn "Error reading from file \"$file\"\n";
56    }
57    close(FILE);
58
59    return($sec);
60 }
61
62
63 #
64 # Write eltorito data into a file
65 #
66 sub writeOutputFile{
67    my($name)=shift;
68    my($value)=shift;
69
70    open(OUT, ">".$name)|| die "$0: Cannot open outputfile \"$name\" for writing. Stop.";
71    print OUT $value;
72    close(OUT);
73 }
74
75
76 #
77 # Usage
78 #
79 sub usage{
80         warn "\n$0 [-hv] [-o outputfilename] cd-image \n",
81             "Script will try to extract an El Torito image from a \n",
82             "bootable CD (or cd-image) given by <cd-image> and write \n",
83             "the data extracted to STDOUT or to a file.\n",
84             "   -h:        This help. \n",
85             "   -v:        Print version of script and exit.\n",
86             "   -o <file>: Write extracted data to file <file> instead of STDOUT.\n",
87             "\n\n";
88         exit 0;    
89 }
90
91
92 # ---------------------------------------------------------------------
93 $ret=getopts('hvo:');
94  
95 if( defined($opt_v) ){
96         warn "Version: $utilVersion \n";
97         exit 0;
98 }
99
100 if( defined($opt_h) || $#ARGV <0 ){
101          usage(0);
102 }        
103
104 if( defined($opt_o) ){
105    $outputFilename="$opt_o";
106 }
107          
108 $imageFile=$ARGV[0];
109
110 if( ! -r $imageFile ){
111         die "Cannot read image/device \"$imageFile\". Aborting\n";
112 }
113
114 #
115 # Read Sector 17 from CD which should contain a Boot Record Volume
116 # descriptor. This descriptor contains at its start the text ($isoIdent)
117 # CD001     and ($toritoSpec)
118 # EL TORITO SPECIFICATION
119 # see http://www.cdpage.com/Compact_Disc_Variations/eltoritoi.html
120 # for details
121 #
122
123 $sector=getSector(17, 1, $imageFile );
124 ($boot, $isoIdent, $version, $toritoSpec,
125         $unUsed, $bootP)= unpack( "Ca5CA32A32V", $sector );
126
127 if( $isoIdent ne "CD001" || $toritoSpec ne "EL TORITO SPECIFICATION" ){
128         die "This data image does not seem to be a bootable CD-image\n";
129 }       
130
131 #
132 # Now fetch the sector of the booting catalog 
133 #
134 $sector=getSector($bootP, 1, $imageFile );
135
136 print STDERR "Booting catalog starts at sector: $bootP \n";
137
138 # The first 32 bytes of this sector contains the validation entry for a
139 # boot. The first byte has to be 01, the next byte determines the
140 # architecture the image is designed for, where 00 is i86, 01 is PowerPC
141 # and 02 is Mac. More data give info about manufacturer, etc.  The 
142 # final two bytes must contain 0x55 and 0xAA respectively (as 
143 # defined by the El Torito standard).
144
145 $validateEntry=substr($sector, 0, 32);
146
147 ($header, $platform, $unUsed, $manufact, $unUsed, $five, $aa)=
148                unpack( "CCvA24vCC", $validateEntry);
149
150 if( $header != 1 || $five != 0x55 || $aa != 0xaa ){
151         die "Invalid Validation Entry on image \n";
152 }
153
154 print STDERR "Manufacturer of CD: $manufact\n";
155 print STDERR "Image architecture: ";
156 print STDERR "x86" if( $platform == 0 );
157 print STDERR "PowerPC" if( $platform == 1 );
158 print STDERR "Mac" if( $platform == 2 );
159 print STDERR "unknown ($platform)" if( $platform > 2 );
160 print STDERR "\n";
161
162 #
163 # Now we examine the initial/defaultentry which follows the validate
164 # entry and has a size of 32 bytes. 
165
166 $initialEntry=substr($sector, 32, 32);
167
168 ($boot, $media, $loadSegment, $systemType, $unUsed, 
169        $sCount, $imgStart, $unUsed)=unpack( "CCvCCvVC", $initialEntry);
170
171 if( $boot != 0x88 ){
172         die "Boot indicator in Initial/Default-Entry is not 0x88. CD is not bootable. \n";
173 }    
174
175 print STDERR "Boot media type is: ";
176 if( $media == 0 ){
177         print STDERR "no emulation";
178         $count=0;
179 }
180 if( $media == 1 ){
181         print STDERR "1.2meg floppy";
182        $count=1200*1024/$vSecSize;  
183 }
184 if( $media == 2 ){
185         print STDERR "1.44meg floppy";
186        $count=1440*1024/$vSecSize;  
187 }
188 if( $media == 3 ){
189         print STDERR "2.88meg floppy";
190        $count=2880*1024/$vSecSize;  
191 }
192 if( $media == 4 ){
193         print STDERR "harddisk";
194         $count=0;
195 }
196 print STDERR "\n";
197
198 # Only use the internal sector counter if the real size is unknown
199 # ($count==0)
200 $cnt=$count==0?$sCount:$count;
201
202 print STDERR "El Torito image starts at sector $imgStart and has $cnt sector(s) of $vSecSize Bytes\n";
203
204 # We are there:
205 # Now read the bootimage to stdout
206 $image=getSector($imgStart, $cnt, $imageFile);
207
208 if( length($outputFilename) ){
209    writeOutputFile($outputFilename, $image);
210    print STDERR "\nImage has been written to file \"$outputFilename\".\n";
211 }else{
212    print "$image";
213    print STDERR "Image has been written to stdout ....\n"; 
214 }