Added jungo-image.py script for backing up and flashing Jungo-based routers
[openwrt/svn-archive/archive.git] / scripts / 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 tftp)
19 \t-s | --server: IP address of tftp server
20 \t-w | --write: initiate loading of redboot (default no modification to flash)
21 \t-v | --verbose: display additional information
22 \t-V | --version: display version information
23 """
24
25 import os
26 import sys
27 import getopt
28 import getpass
29 import telnetlib
30 import string
31 import binascii
32 import socket
33 import thread
34 import SocketServer
35 import SimpleHTTPServer
36
37 server = ""
38 HOST = "192.168.1.1"
39 PORT = 8080
40 user = "admin"
41 #password = getpass.getpass()
42 password = "password1"
43 proto = "http"
44 imagefile = "redboot.bin"
45 dumpfile = ""
46 verbose = 0
47 no_dump = 0
48 dumplen = 0x10000
49 write_image = 0
50 flashsize=8*1024*1024
51
52 ####################
53
54 def start_server():
55 httpd = SocketServer.TCPServer((server,PORT),SimpleHTTPServer.SimpleHTTPRequestHandler)
56 thread.start_new_thread(httpd.serve_forever,())
57
58 ####################
59
60 def get_flash_size():
61 tn.write("cat /proc/mtd\n")
62 # wait for prompt
63 buf = tn.read_until("Returned 0", 3)
64 if buf:
65 i = buf.find('mtd0:')
66 if i > 0:
67 flashsize = int(buf[i+6:].split()[0],16)
68
69 def image_dump(tn, dumpfile):
70 if not dumpfile:
71 tn.write("ver\n");
72 buf = tn.read_until("Returned 0")
73 i = buf.find("Platform:")
74 if i < 0:
75 platform="jungo"
76 else:
77 platform=buf[i+9:].split()[0]
78
79 tn.write("ifconfig br0\n");
80 buf = tn.read_until("Returned 0")
81
82 i = buf.find("MAC=")
83 if i < 0:
84 print "No MAC address found! (use -f option)"
85 sys.exit(1)
86 dumpfile = "%s-%s.bin" % (platform, buf[i+4:i+21].replace(':',''))
87 else:
88 tn.write("\n")
89
90 print "Dumping flash contents (%dMB) to %s\n" % (flashsize/1048576, dumpfile)
91 f = open(dumpfile, "wb")
92
93 for addr in range(flashsize/dumplen):
94 if verbose:
95 sys.stdout.write('.')
96 sys.stdout.flush()
97
98 tn.write("flash_dump -r 0x%x -l %d -4\n" % (addr*dumplen, dumplen))
99 tn.read_until("\n")
100
101 count = addr*dumplen
102 while 1:
103 buf = tn.read_until("\n")
104 if buf.strip() == "Returned 0":
105 break
106 s = buf.split()
107 if s and s[0][-1] == ':':
108 a=int(s[0][:-1],16)
109 if a != count:
110 print "Format error: %x != %x"%(a,count)
111 sys.exit(2)
112 count += 16
113 f.write(binascii.a2b_hex(string.join(s[1:],'')))
114 tn.read_until(">",1)
115
116 f.close()
117
118 def telnet_option(sock,cmd,option):
119 #print "Option: %d %d" % (ord(cmd), ord(option))
120 if cmd == telnetlib.DO:
121 c=telnetlib.WILL
122 elif cmd == telnetlib.WILL:
123 c=telnetlib.DO
124 sock.sendall(telnetlib.IAC + c + option)
125
126 def telnet_timeout():
127 print "Fatal error: telnet timeout!"
128 sys.exit(1)
129
130 def usage():
131 print __doc__ % os.path.basename(sys.argv[0])
132
133 ####################
134
135 try:
136 opts, args = getopt.getopt(sys.argv[1:], "hdf:u:p:P:s:vVw", \
137 ["help", "dump", "file=", "user=", "pass=", "proto=","server=", "verbose", "version", "write"])
138 except getopt.GetoptError:
139 # print help information and exit:
140 usage()
141 sys.exit(1)
142
143 for o, a in opts:
144 if o in ("-h", "--help"):
145 usage()
146 sys.exit(1)
147 if o in ("-V", "--version"):
148 print "%s: 0.6" % sys.argv[0]
149 sys.exit(1)
150 if o in ("-d", "--no-dump"):
151 no_dump = 1
152 if o in ("-f", "--file"):
153 dumpfile = a
154 if o in ("-s", "--server"):
155 server = a
156 if o in ("-u", "--user"):
157 user = a
158 if o in ("-p", "--pass"):
159 password = a
160 if o in ("-P", "--proto"):
161 proto = a
162 if o in ("-w", "--write"):
163 write_image = 1
164 if o in ("-v", "--verbose"):
165 verbose = 1
166
167 # make sure we have enough arguments
168 if len(args) > 0:
169 HOST = args[0]
170
171 if len(args) == 2:
172 imagefile = args[1]
173
174 ####################
175 # create a telnet session to the router
176 try:
177 tn = telnetlib.Telnet(HOST)
178 except socket.error, msg:
179 print "Unable to establish telnet session to %s: %s" % (HOST, msg)
180 sys.exit(1)
181
182 tn.set_option_negotiation_callback(telnet_option)
183
184 buf = tn.read_until("Username: ", 3)
185 if not buf:
186 telnet_timeout()
187 tn.write(user+"\n")
188 if password:
189 buf = tn.read_until("Password: ", 3)
190 if not buf:
191 telnet_timeout()
192 tn.write(password+"\n")
193
194 # wait for prompt
195 buf = tn.read_until("> ", 3)
196 if not buf:
197 telnet_timeout()
198
199 get_flash_size()
200
201 if not no_dump:
202 image_dump(tn, dumpfile)
203
204 # write image file image
205 if not server:
206 server = tn.get_socket().getsockname()[0]
207 if proto == "http":
208 cmd = "load -u %s://%s:%d/%s -r 0\n" % (proto, server, PORT, imagefile)
209 else:
210 cmd = "load -u %s://%s/%s -r 0\n" % (proto, server, imagefile)
211 print cmd
212 if write_image:
213 if proto == "http":
214 start_server()
215
216 tn.write("unlock 0 0x%x\n" % flashsize)
217 buf = tn.read_until("Returned 0")
218
219 tn.write(cmd)
220 buf = tn.read_until("Returned 0")
221
222 tn.write("exit\n")
223 tn.close()