1#!/usr/bin/perl 2# DVB firmware extractor 3# 4# (c) 2004 Andrew de Quincey 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21use File::Temp qw/ tempdir /; 22use IO::Handle; 23 24@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", 25 "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002" ); 26 27# Check args 28syntax() if (scalar(@ARGV) != 1); 29$cid = $ARGV[0]; 30 31# Do it! 32for($i=0; $i < scalar(@components); $i++) { 33 if ($cid eq $components[$i]) { 34 $outfile = eval($cid); 35 die $@ if $@; 36 print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n"; 37 exit(0); 38 } 39} 40 41# If we get here, it wasn't found 42print STDERR "Unknown component \"$cid\"\n"; 43syntax(); 44 45 46 47 48# --------------------------------------------------------------- 49# Firmware-specific extraction subroutines 50 51sub sp8870 { 52 my $sourcefile = "tt_Premium_217g.zip"; 53 my $url = "http://www.technotrend.de/new/217g/$sourcefile"; 54 my $hash = "53970ec17a538945a6d8cb608a7b3899"; 55 my $outfile = "dvb-fe-sp8870.fw"; 56 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 57 58 checkstandard(); 59 60 wgetfile($sourcefile, $url); 61 unzip($sourcefile, $tmpdir); 62 verify("$tmpdir/software/OEM/HE/App/boot/SC_MAIN.MC", $hash); 63 copy("$tmpdir/software/OEM/HE/App/boot/SC_MAIN.MC", $outfile); 64 65 $outfile; 66} 67 68sub sp887x { 69 my $sourcefile = "Dvbt1.3.57.6.zip"; 70 my $url = "http://www.avermedia.com/software/$sourcefile"; 71 my $cabfile = "DVBT Net Ver1.3.57.6/disk1/data1.cab"; 72 my $hash = "237938d53a7f834c05c42b894ca68ac3"; 73 my $outfile = "dvb-fe-sp887x.fw"; 74 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 75 76 checkstandard(); 77 checkunshield(); 78 79 wgetfile($sourcefile, $url); 80 unzip($sourcefile, $tmpdir); 81 unshield("$tmpdir/$cabfile", $tmpdir); 82 verify("$tmpdir/sc_main.mc", $hash); 83 copy("$tmpdir/sc_main.mc", $outfile); 84 85 $outfile; 86} 87 88sub tda10045 { 89 my $sourcefile = "tt_budget_217g.zip"; 90 my $url = "http://www.technotrend.de/new/217g/$sourcefile"; 91 my $hash = "2105fd5bf37842fbcdfa4bfd58f3594a"; 92 my $outfile = "dvb-fe-tda10045.fw"; 93 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 94 95 checkstandard(); 96 97 wgetfile($sourcefile, $url); 98 unzip($sourcefile, $tmpdir); 99 extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x37ef9, 30555, "$tmpdir/fwtmp"); 100 verify("$tmpdir/fwtmp", $hash); 101 copy("$tmpdir/fwtmp", $outfile); 102 103 $outfile; 104} 105 106sub tda10046 { 107 my $sourcefile = "tt_budget_217g.zip"; 108 my $url = "http://www.technotrend.de/new/217g/$sourcefile"; 109 my $hash = "a25b579e37109af60f4a36c37893957c"; 110 my $outfile = "dvb-fe-tda10046.fw"; 111 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 112 113 checkstandard(); 114 115 wgetfile($sourcefile, $url); 116 unzip($sourcefile, $tmpdir); 117 extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp"); 118 verify("$tmpdir/fwtmp", $hash); 119 copy("$tmpdir/fwtmp", $outfile); 120 121 $outfile; 122} 123 124sub av7110 { 125 my $sourcefile = "dvb-ttpci-01.fw-261c"; 126 my $url = "http://www.linuxtv.org/download/dvb/firmware/$sourcefile"; 127 my $hash = "7b263de6b0b92d2347319c65adc7d4fb"; 128 my $outfile = "dvb-ttpci-01.fw"; 129 130 checkstandard(); 131 132 wgetfile($sourcefile, $url); 133 verify($sourcefile, $hash); 134 copy($sourcefile, $outfile); 135 136 $outfile; 137} 138 139sub dec2000t { 140 my $sourcefile = "dec217g.exe"; 141 my $url = "http://hauppauge.lightpath.net/de/$sourcefile"; 142 my $hash = "bd86f458cee4a8f0a8ce2d20c66215a9"; 143 my $outfile = "dvb-ttusb-dec-2000t.fw"; 144 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 145 146 checkstandard(); 147 148 wgetfile($sourcefile, $url); 149 unzip($sourcefile, $tmpdir); 150 verify("$tmpdir/software/OEM/STB/App/Boot/STB_PC_T.bin", $hash); 151 copy("$tmpdir/software/OEM/STB/App/Boot/STB_PC_T.bin", $outfile); 152 153 $outfile; 154} 155 156sub dec2540t { 157 my $sourcefile = "dec217g.exe"; 158 my $url = "http://hauppauge.lightpath.net/de/$sourcefile"; 159 my $hash = "53e58f4f5b5c2930beee74a7681fed92"; 160 my $outfile = "dvb-ttusb-dec-2540t.fw"; 161 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 162 163 checkstandard(); 164 165 wgetfile($sourcefile, $url); 166 unzip($sourcefile, $tmpdir); 167 verify("$tmpdir/software/OEM/STB/App/Boot/STB_PC_X.bin", $hash); 168 copy("$tmpdir/software/OEM/STB/App/Boot/STB_PC_X.bin", $outfile); 169 170 $outfile; 171} 172 173sub dec3000s { 174 my $sourcefile = "dec217g.exe"; 175 my $url = "http://hauppauge.lightpath.net/de/$sourcefile"; 176 my $hash = "b013ececea83f4d6d8d2a29ac7c1b448"; 177 my $outfile = "dvb-ttusb-dec-3000s.fw"; 178 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 179 180 checkstandard(); 181 182 wgetfile($sourcefile, $url); 183 unzip($sourcefile, $tmpdir); 184 verify("$tmpdir/software/OEM/STB/App/Boot/STB_PC_S.bin", $hash); 185 copy("$tmpdir/software/OEM/STB/App/Boot/STB_PC_S.bin", $outfile); 186 187 $outfile; 188} 189 190sub vp7041 { 191 my $sourcefile = "2.422.zip"; 192 my $url = "http://www.twinhan.com/files/driver/USB-Ter/$sourcefile"; 193 my $hash = "e88c9372d1f66609a3e7b072c53fbcfe"; 194 my $outfile = "dvb-vp7041-2.422.fw"; 195 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 196 197 checkstandard(); 198 199 wgetfile($sourcefile, $url); 200 unzip($sourcefile, $tmpdir); 201 extract("$tmpdir/VisionDTV/Drivers/Win2K&XP/UDTTload.sys", 12503, 3036, "$tmpdir/fwtmp1"); 202 extract("$tmpdir/VisionDTV/Drivers/Win2K&XP/UDTTload.sys", 2207, 10274, "$tmpdir/fwtmp2"); 203 204 my $CMD = "\000\001\000\222\177\000"; 205 my $PAD = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; 206 my ($FW); 207 open $FW, ">$tmpdir/fwtmp3"; 208 print $FW "$CMD\001$PAD"; 209 print $FW "$CMD\001$PAD"; 210 appendfile($FW, "$tmpdir/fwtmp1"); 211 print $FW "$CMD\000$PAD"; 212 print $FW "$CMD\001$PAD"; 213 appendfile($FW, "$tmpdir/fwtmp2"); 214 print $FW "$CMD\001$PAD"; 215 print $FW "$CMD\000$PAD"; 216 close($FW); 217 218 verify("$tmpdir/fwtmp3", $hash); 219 copy("$tmpdir/fwtmp3", $outfile); 220 221 $outfile; 222} 223 224sub dibusb { 225 my $url = "http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-5.0.0.11.fw?rev=1.1&content-type=text/plain"; 226 my $outfile = "dvb-dibusb-5.0.0.11.fw"; 227 my $hash = "fa490295a527360ca16dcdf3224ca243"; 228 229 checkstandard(); 230 231 wgetfile($outfile, $url); 232 verify($outfile,$hash); 233 234 $outfile; 235} 236 237sub nxt2002 { 238 my $sourcefile = "Broadband4PC_4_2_11.zip"; 239 my $url = "http://www.bbti.us/download/windows/$sourcefile"; 240 my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a"; 241 my $outfile = "dvb-fe-nxt2002.fw"; 242 my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); 243 244 checkstandard(); 245 246 wgetfile($sourcefile, $url); 247 unzip($sourcefile, $tmpdir); 248 verify("$tmpdir/SkyNETU.sys", $hash); 249 extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile); 250 251 $outfile; 252} 253 254# --------------------------------------------------------------- 255# Utilities 256 257sub checkstandard { 258 if (system("which unzip > /dev/null 2>&1")) { 259 die "This firmware requires the unzip command - see ftp://ftp.info-zip.org/pub/infozip/UnZip.html\n"; 260 } 261 if (system("which md5sum > /dev/null 2>&1")) { 262 die "This firmware requires the md5sum command - see http://www.gnu.org/software/coreutils/\n"; 263 } 264 if (system("which wget > /dev/null 2>&1")) { 265 die "This firmware requires the wget command - see http://wget.sunsite.dk/\n"; 266 } 267} 268 269sub checkunshield { 270 if (system("which unshield > /dev/null 2>&1")) { 271 die "This firmware requires the unshield command - see http://sourceforge.net/projects/synce/\n"; 272 } 273} 274 275sub wgetfile { 276 my ($sourcefile, $url) = @_; 277 278 if (! -f $sourcefile) { 279 system("wget -O \"$sourcefile\" \"$url\"") and die "wget failed - unable to download firmware"; 280 } 281} 282 283sub unzip { 284 my ($sourcefile, $todir) = @_; 285 286 $status = system("unzip -q -o -d \"$todir\" \"$sourcefile\" 2>/dev/null" ); 287 if ((($status >> 8) > 2) || (($status & 0xff) != 0)) { 288 die ("unzip failed - unable to extract firmware"); 289 } 290} 291 292sub unshield { 293 my ($sourcefile, $todir) = @_; 294 295 system("unshield -d \"$todir\" \"$sourcefile\" > /dev/null" ) and die ("unshield failed - unable to extract firmware"); 296} 297 298sub verify { 299 my ($filename, $hash) = @_; 300 my ($testhash); 301 302 open(CMD, "md5sum \"$filename\"|"); 303 $testhash = <CMD>; 304 $testhash =~ /([a-zA-Z0-9]*)/; 305 $testhash = $1; 306 close CMD; 307 die "Hash of extracted file does not match!\n" if ($testhash ne $hash); 308} 309 310sub copy { 311 my ($from, $to) = @_; 312 313 system("cp -f \"$from\" \"$to\"") and die ("cp failed"); 314} 315 316sub extract { 317 my ($infile, $offset, $length, $outfile) = @_; 318 my ($chunklength, $buf, $rcount); 319 320 open INFILE, "<$infile"; 321 open OUTFILE, ">$outfile"; 322 sysseek(INFILE, $offset, SEEK_SET); 323 while($length > 0) { 324 # Calc chunk size 325 $chunklength = 2048; 326 $chunklength = $length if ($chunklength > $length); 327 328 $rcount = sysread(INFILE, $buf, $chunklength); 329 die "Ran out of data\n" if ($rcount != $chunklength); 330 syswrite(OUTFILE, $buf); 331 $length -= $rcount; 332 } 333 close INFILE; 334 close OUTFILE; 335} 336 337sub appendfile { 338 my ($FH, $infile) = @_; 339 my ($buf); 340 341 open INFILE, "<$infile"; 342 while(1) { 343 $rcount = sysread(INFILE, $buf, 2048); 344 last if ($rcount == 0); 345 print $FH $buf; 346 } 347 close(INFILE); 348} 349 350sub syntax() { 351 print STDERR "syntax: get_dvb_firmware <component>\n"; 352 print STDERR "Supported components:\n"; 353 for($i=0; $i < scalar(@components); $i++) { 354 print STDERR "\t" . $components[$i] . "\n"; 355 } 356 exit(1); 357} 358

