Also move jungo-image.py to scripts/flashing
[openwrt/svn-archive/archive.git] / scripts / flashing / jungo-image.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2008 (C) Jose Vasconcellos <jvasco@verizon.net>
4 #
5 # A script that can communicate with jungo-based routers
6 # (such as MI424-WR, USR8200 and WRV54G) to backup the installed
7 # firmware and replace the boot loader.
8 #
9 # Tested with Python 2.5 on Linux and Windows
10 #
11 """Usage: %s [options] <IP_address> [redboot.bin]
12 Valid options:
13 \t-h | --help: usage statement
14 \t-d | --no-dump: don't create a flash dump
15 \t-f | --file: use <filename> to store dump contents
16 \t-u | --user: provide username (default admin)
17 \t-p | --pass: provide password (default password1)
18 \t-P | --proto: set transfer protocol (default http)
19 \t --port: set port for http (default 8080)
20 \t-s | --server: IP address of tftp server
21 \t-w | --write: initiate loading of redboot (default no modification to flash)
22 \t-q | --quiet: don't display unnecessary information
23 \t-v | --verbose: display progress information
24 \t-V | --version: display version information
25 """
26
27 import os
28 import sys
29 import getopt
30 import getpass
31 import telnetlib
32 import string
33 import binascii
34 import socket
35 import thread
36 import SocketServer
37 import SimpleHTTPServer
38
39 server = ""
40 HOST = "192.168.1.1"
41 PORT = 8080
42 user = "admin"
43 #password = getpass.getpass()
44 password = "password1"
45 proto = "http"
46 imagefile = "redboot.bin"
47 dumpfile = ""
48 verbose = 1
49 no_dump = 0
50 dumplen = 0x10000
51 write_image = 0
52 flashsize=4*1024*1024
53 #device="br0"
54 device="ixp0"
55
56 ####################
57
58 def start_server():
59 httpd = SocketServer.TCPServer((server,PORT),SimpleHTTPServer.SimpleHTTPRequestHandler)
60 thread.start_new_thread(httpd.serve_forever,())
61
62 ####################
63
64 def get_flash_size():
65 global flashsize
66 tn.write("cat /proc/mtd\n")
67 # wait for prompt
68 buf = tn.read_until("Returned 0", 3)
69 if buf:
70 i = buf.find('mtd0:')
71 if i > 0:
72 flashsize = int(buf[i+6:].split()[0],16)
73 else:
74 print "Can't find mtd0!"
75 else:
76 print "Can't access /proc/mtd!"
77
78 def image_dump(tn, dumpfile):
79 if not dumpfile:
80 tn.write("ver\n");
81 buf = tn.read_until("Returned 0")
82 i = buf.find("Platform:")
83 if i < 0:
84 platform="jungo"
85 else:
86 line=buf[i+9:]
87 i=line.find('\n')
88 platform=line[:i].split()[-1]
89
90 tn.write("ifconfig -v %s\n" % device);
91 buf = tn.read_until("Returned 0")
92
93 i = buf.find("mac = 0")
94 if i > 0:
95 i += 6
96 else:
97 print "No MAC address found! (use -f option)"
98 sys.exit(1)
99 dumpfile = "%s-%s.bin" % (platform, buf[i:i+17].replace(':',''))
100 else:
101 tn.write("\n")
102
103 print "Dumping flash contents (%dMB) to %s" % (flashsize/1048576, dumpfile)
104 f = open(dumpfile, "wb")
105
106 t=flashsize/dumplen
107 for addr in range(t):
108 if verbose:
109 sys.stdout.write('\r%d%%'%(100*addr/t))
110 sys.stdout.flush()
111
112 tn.write("flash_dump -r 0x%x -l %d -4\n" % (addr*dumplen, dumplen))
113 tn.read_until("\n")
114
115 count = addr*dumplen
116 while 1:
117 buf = tn.read_until("\n")
118 if buf.strip() == "Returned 0":
119 break
120 s = buf.split()
121 if s and s[0][-1] == ':':
122 a=int(s[0][:-1],16)
123 if a != count:
124 print "Format error: %x != %x"%(a,count)
125 sys.exit(2)
126 count += 16
127 f.write(binascii.a2b_hex(string.join(s[1:],'')))
128 tn.read_until(">",1)
129
130 f.close()
131 if verbose:
132 print ""
133
134 def telnet_option(sock,cmd,option):
135 #print "Option: %d %d" % (ord(cmd), ord(option))
136 if cmd == telnetlib.DO:
137 c=telnetlib.WILL
138 elif cmd == telnetlib.WILL:
139 c=telnetlib.DO
140 sock.sendall(telnetlib.IAC + c + option)
141
142 def telnet_timeout():
143 print "Fatal error: telnet timeout!"
144 sys.exit(1)
145
146 def usage():
147 print __doc__ % os.path.basename(sys.argv[0])
148
149 ####################
150
151 try:
152 opts, args = getopt.getopt(sys.argv[1:], "hdf:u:qp:P:s:vVw", \
153 ["help", "dump", "file=", "user=", "pass=", "proto=", "proto=",
154 "quiet=", "server=", "verbose", "version", "write"])
155 except getopt.GetoptError:
156 # print help information and exit:
157 usage()
158 sys.exit(1)
159
160 for o, a in opts:
161 if o in ("-h", "--help"):
162 usage()
163 sys.exit(1)
164 if o in ("-V", "--version"):
165 print "%s: 0.7" % sys.argv[0]
166 sys.exit(1)
167 if o in ("-d", "--no-dump"):
168 no_dump = 1
169 if o in ("-f", "--file"):
170 dumpfile = a
171 if o in ("-s", "--server"):
172 server = a
173 if o in ("-u", "--user"):
174 user = a
175 if o in ("-p", "--pass"):
176 password = a
177 if o in ("-P", "--proto"):
178 proto = a
179 if o in ("--port"):
180 PORT = a
181 if o in ("-w", "--write"):
182 write_image = 1
183 if o in ("-q", "--quiet"):
184 verbose = 0
185 if o in ("-v", "--verbose"):
186 verbose = 1
187
188 # make sure we have enough arguments
189 if len(args) > 0:
190 HOST = args[0]
191
192 if len(args) == 2:
193 imagefile = args[1]
194
195 ####################
196 # create a telnet session to the router
197 try:
198 tn = telnetlib.Telnet(HOST)
199 except socket.error, msg:
200 print "Unable to establish telnet session to %s: %s" % (HOST, msg)
201 sys.exit(1)
202
203 tn.set_option_negotiation_callback(telnet_option)
204
205 buf = tn.read_until("Username: ", 3)
206 if not buf:
207 telnet_timeout()
208 tn.write(user+"\n")
209 if password:
210 buf = tn.read_until("Password: ", 3)
211 if not buf:
212 telnet_timeout()
213 tn.write(password+"\n")
214
215 # wait for prompt
216 buf = tn.read_until("> ", 3)
217 if not buf:
218 telnet_timeout()
219
220 get_flash_size()
221
222 if not no_dump:
223 image_dump(tn, dumpfile)
224
225 if write_image:
226 if not os.access(imagefile, os.R_OK):
227 print "File access error: %s" % (imagefile)
228 sys.exit(3)
229
230 splitpath = os.path.split(imagefile)
231 # make sure we're in the directory where the image is located
232 if splitpath[0]:
233 os.chdir(splitpath[0])
234
235 # write image file image
236 if not server:
237 server = tn.get_socket().getsockname()[0]
238 if proto == "http":
239 cmd = "load -u %s://%s:%d/%s -r 0\n" % (proto, server, PORT, splitpath[1])
240 else:
241 cmd = "load -u %s://%s/%s -r 0\n" % (proto, server, splitpath[1])
242
243 if proto == "http":
244 start_server()
245
246 if verbose:
247 print "Unlocking flash..."
248 tn.write("unlock 0 0x%x\n" % flashsize)
249 buf = tn.read_until("Returned 0")
250
251 if verbose:
252 print "Writing new image..."
253 print cmd,
254 tn.write(cmd)
255 buf = tn.read_until("Returned 0")
256
257 tn.write("exit\n")
258 tn.close()