OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #!/usr/bin/env perl |
2 | # |
||
3 | # D-Link DSL-G6x4T flash utility |
||
4 | # |
||
5 | # Copyright (C) 2005 Felix Fietkau <mailto@nbd.name> |
||
6 | # based on fbox recovery util by Enrik Berkhan |
||
7 | # |
||
8 | # This program is free software; you can redistribute it and/or modify |
||
9 | # it under the terms of the GNU General Public License as published by |
||
10 | # the Free Software Foundation; either version 2 of the License, or |
||
11 | # (at your option) any later version. |
||
12 | # |
||
13 | # This program is distributed in the hope that it will be useful, |
||
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | # GNU General Public License for more details. |
||
17 | # |
||
18 | # You should have received a copy of the GNU General Public License |
||
19 | # along with this program; if not, write to the Free Software |
||
20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
21 | # |
||
22 | |||
23 | use IO::Socket::INET; |
||
24 | use IO::Select; |
||
25 | use Socket; |
||
26 | use strict; |
||
27 | use warnings; |
||
28 | |||
29 | sub usage() { |
||
30 | print STDERR "Usage: $0 <ip> [firmware.bin]\n\n"; |
||
31 | exit 0; |
||
32 | } |
||
33 | |||
34 | my $ip = shift @ARGV; |
||
35 | $ip and $ip =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ or usage(); |
||
36 | |||
37 | my $setip = unpack("N", inet_aton($ip)); |
||
38 | $setip > 0 or usage(); |
||
39 | |||
40 | my @packets; |
||
41 | foreach my $ver ([18, 1], [22, 2]) { |
||
42 | push @packets, pack("vCCVNV", 0, @$ver, 1, $setip, 0); |
||
43 | } |
||
44 | print STDERR "Looking for device: "; |
||
45 | my $scanning; |
||
46 | my $box; |
||
47 | |||
48 | my $probe = IO::Socket::INET->new(Proto => 'udp', |
||
49 | Broadcast => 1, |
||
50 | LocalAddr => $ip, |
||
51 | LocalPort => 5035) or die "socket: $!"; |
||
52 | my $sel = IO::Select->new($probe); |
||
53 | my $packet = pack("vCCVNV", 0, 18, 1, 1, 0, 0); |
||
54 | my $broadcast = sockaddr_in(5035, INADDR_BROADCAST); |
||
55 | |||
56 | $probe->send($packet, 0, $broadcast); |
||
57 | |||
58 | |||
59 | scan_again: |
||
60 | print "Looking for Fritz!Box "; |
||
61 | my @boxes = (); |
||
62 | my $peer; |
||
63 | $scanning = 100; |
||
64 | print "o"; |
||
65 | while($scanning) { |
||
66 | my $reply; |
||
67 | my @ready; |
||
68 | |||
69 | if (@ready = $sel->can_read(0.2)) { |
||
70 | $peer = $probe->recv($reply, 16); |
||
71 | next if (length($reply) < 16); |
||
72 | my ($port, $addr) = sockaddr_in($peer); |
||
73 | my ($major, $minor1, $minor2, $code, $addr2) = unpack("vCCVV", $reply); |
||
74 | $addr2 = pack("N", $addr2); |
||
75 | if ($code == 2) { |
||
76 | print "O"; |
||
77 | push @boxes, [$major, $minor1, $minor2, $addr, $addr2]; |
||
78 | $scanning = 2 if ($scanning > 2); |
||
79 | } |
||
80 | } else { |
||
81 | $scanning--; |
||
82 | if (scalar @boxes == 0) { |
||
83 | $probe->send($packet, 0, $broadcast); |
||
84 | print "o"; |
||
85 | } else { |
||
86 | print "."; |
||
87 | } |
||
88 | } |
||
89 | } |
||
90 | |||
91 | if (scalar @boxes == 0) { |
||
92 | print " none found, giving up.\n"; |
||
93 | exit 1; |
||
94 | } else { |
||
95 | print " found!\n"; |
||
96 | } |
||
97 | |||
98 | { |
||
99 | package ADAM2FTP; |
||
100 | use base qw(Net::FTP); |
||
101 | # ADAM2 requires upper case commands, some brain dead firewall doesn't ;-) |
||
102 | sub _USER { shift->command("USER",@_)->response() } |
||
103 | sub _PASV { shift->command("P\@SW")->response() == Net::FTP::CMD_OK } |
||
104 | sub _GETENV { |
||
105 | my $ftp = shift; |
||
106 | my ($ok, $name, $value); |
||
107 | |||
108 | $ftp->command("GETENV",@_); |
||
109 | while(length($ok = $ftp->response()) < 1) { |
||
110 | my $line = $ftp->getline(); |
||
111 | unless (defined($value)) { |
||
112 | chomp($line); |
||
113 | ($name, $value) = split(/\s+/, $line, 2); |
||
114 | } |
||
115 | } |
||
116 | $ftp->debug_print(0, "getenv: $value\n") |
||
117 | if $ftp->debug(); |
||
118 | return $value; |
||
119 | } |
||
120 | sub getenv { |
||
121 | my $ftp = shift; |
||
122 | my $name = shift; |
||
123 | return $ftp->_GETENV($name); |
||
124 | } |
||
125 | sub _REBOOT { shift->command("REBOOT")->response() == Net::FTP::CMD_OK } |
||
126 | sub reboot { |
||
127 | my $ftp = shift; |
||
128 | $ftp->_REBOOT; |
||
129 | $ftp->close; |
||
130 | } |
||
131 | sub check { |
||
132 | my $ftp = shift; |
||
133 | |||
134 | delete ${*$ftp}{'net_ftp_port'}; |
||
135 | delete ${*$ftp}{'net_ftp_pasv'}; |
||
136 | |||
137 | my $data = $ftp->_data_cmd('CHECK' ,@_) or return undef; |
||
138 | my $sum; |
||
139 | if (${${*$ftp}{'net_cmd_resp'}}[0] =~ /^Flash check 0x([0-9A-F]{8})/) { |
||
140 | $sum = hex($1); |
||
141 | } |
||
142 | $data->_close(); |
||
143 | return $sum; |
||
144 | } |
||
145 | } |
||
146 | |||
147 | # passive mode geht mit Net::FTP nicht, connected zu spaet fuer ADAM2! |
||
148 | my $ftp = ADAM2FTP->new($ip, Passive => 0, Debug => 0, Timeout => 600) |
||
149 | or die "can't FTP ADAM2"; |
||
150 | $ftp->login("adam2", "adam2") or die "can't login adam2"; |
||
151 | $ftp->binary(); |
||
152 | my $pid = $ftp->getenv('ProductID'); |
||
153 | my $hwrev = $ftp->getenv('HWRevision'); |
||
154 | my $fwrev = $ftp->getenv('firmware_info'); |
||
155 | my $ulrev = $ftp->getenv('urlader-version'); |
||
156 | |||
157 | print "Product ID: $pid\n"; |
||
158 | print "Hardware Revision: $hwrev\n"; |
||
159 | print "Urlader Revision: $ulrev\n"; |
||
160 | print "Firmware Revision: $fwrev\n"; |
||
161 | |||
162 | $ftp->hash(\*STDOUT, 64 * 1024); |
||
163 | |||
164 | my $file = shift @ARGV; |
||
165 | $file || exit 0; |
||
166 | |||
167 | open FILE, "<$file" or die "can't open firmware file\n"; |
||
168 | |||
169 | my $mtd0 = $ftp->getenv("mtd0"); |
||
170 | my $mtd1 = $ftp->getenv("mtd1"); |
||
171 | my ($ksize, $fssize); |
||
172 | |||
173 | $mtd1 =~ /^(0x\w+),(0x\w+)$/ and $ksize = hex($2) - hex($1); |
||
174 | $mtd0 =~ /^(0x\w+),(0x\w+)$/ and $fssize = hex($2) - hex($1); |
||
175 | $ksize and $fssize or die 'cannot read partition offsets'; |
||
176 | printf STDERR "Available flash space: 0x%08x (0x%08x + 0x%08x)\n", $ksize + $fssize, $ksize, $fssize; |
||
177 | |||
178 | $ftp->command("MEDIA FLSH")->response(); |
||
179 | $ftp->binary(); |
||
180 | print STDERR "Writing to mtd1...\n"; |
||
181 | |||
182 | my $dc = $ftp->stor("fs mtd1"); |
||
183 | $dc or die "can't open data connection\n"; |
||
184 | my $rbytes = 1; |
||
185 | |||
186 | while (($ksize > 0) and ($rbytes > 0)) { |
||
187 | my $buffer; |
||
188 | my $len = ($ksize > 1024 ? 1024 : $ksize); |
||
189 | $rbytes = read FILE, $buffer, $len; |
||
190 | $rbytes and $ksize -= $dc->write($buffer, $rbytes, 600); |
||
191 | } |
||
192 | |||
193 | $dc->close(); |
||
194 | $rbytes or die "no more data left to write\n"; |
||
195 | |||
196 | print STDERR "Writing to mtd0...\n"; |
||
197 | |||
198 | $dc = $ftp->stor("fs mtd0"); |
||
199 | $dc or die "can't open data connection\n"; |
||
200 | |||
201 | while (($fssize > 0) and ($rbytes > 0)) { |
||
202 | my $buffer; |
||
203 | my $len = ($fssize > 1024 ? 1024 : $fssize); |
||
204 | $rbytes = read FILE, $buffer, $len; |
||
205 | $rbytes and $fssize -= $dc->write($buffer, $rbytes, 600); |
||
206 | } |
||
207 | |||
208 | $dc->close(); |
||
209 | $ftp->reboot(); |