a99253dd493a36c1d1d5d8213de32e137ce51767
[openwrt.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()