ath9k: enable u-apsd support
[openwrt.git] / scripts / flashing / jungo-image.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2008, 2009 (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> [image.bin | url]
12 Valid options:
13 \t-h | --help: usage statement
14 \t-d | --dump: 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     --port: set port for http (default 8080)
19 \t-q | --quiet: don't display unnecessary information
20 \t-r | --reboot: reboot target on successful transfer
21 \t-V | --version: display version information
22
23 If no image (or url) is given, a flash dump is created.
24 A built-in http server is used when an image file is provided.
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 reboot = 0
40 HOST = "192.168.1.1"
41 PORT = 8080
42 user = "admin"
43 #password = getpass.getpass()
44 password = "password1"
45 proto = "http"
46 url = ""
47 imagefile = ""
48 dumpfile = ""
49 verbose = 1
50 do_dump = 0
51 dumplen = 0x10000
52 flashsize=4*1024*1024
53 #device="br0"
54 device="ixp0"
55
56 ####################
57
58 def start_server(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     # make sure we don't have an A0 stepping
66     tn.write("cat /proc/cpuinfo\n")
67     buf = tn.read_until("Returned 0", 3)
68     if not buf:
69         print "Unable to obtain CPU information; make sure to not use A0 stepping!"
70     elif buf.find('rev 0') > 0:
71         print "Warning: IXP42x stepping A0 detected!"
72         if imagefile or url:
73             print "Error: No linux support for A0 stepping!"
74             sys.exit(2)
75
76     # now get flash size
77     tn.write("cat /proc/mtd\n")
78     buf = tn.read_until("Returned 0", 3)
79     if buf:
80         i = buf.find('mtd0:')
81         if i > 0:
82             return int(buf[i+6:].split()[0],16)
83         # use different command
84         tn.write("flash_layout\n")
85         buf = tn.read_until("Returned 0", 3)
86         i = buf.rfind('Range ')
87         if i > 0:
88             return int(buf[i+17:].split()[0],16)
89         print "Can't determine flash size!"
90     else:
91         print "Unable to obtain flash size!"
92     sys.exit(2)
93
94 def image_dump(tn, dumpfile):
95     if not dumpfile:
96         tn.write("ver\n");
97         buf = tn.read_until("Returned 0",2)
98         i = buf.find("Platform:")
99         if i < 0:
100             platform="jungo"
101         else:
102             line=buf[i+9:]
103             i=line.find('\n')
104             platform=line[:i].split()[-1]
105
106         tn.write("rg_conf_print /dev/%s/mac\n" % device);
107         buf = tn.read_until("Returned 0",3)
108
109         i = buf.find("mac(")
110         if i > 0:
111             i += 4
112         else:
113             print "No MAC address found! (use -f option)"
114             sys.exit(1)
115         dumpfile = "%s-%s.bin" % (platform, buf[i:i+17].replace(':',''))
116     else:
117         tn.write("\n")
118
119     print "Dumping flash contents (%dMB) to %s" % (flashsize/1048576, dumpfile)
120     f = open(dumpfile, "wb")
121
122     t=flashsize/dumplen
123     for addr in range(t):
124         if verbose:
125             sys.stdout.write('\r%d%%'%(100*addr/t))
126             sys.stdout.flush()
127
128         tn.write("flash_dump -r 0x%x -l %d -4\n" % (addr*dumplen, dumplen))
129         tn.read_until("\n")
130
131         count = addr*dumplen
132         while 1:
133             buf = tn.read_until("\n")
134             if buf.strip() == "Returned 0":
135                 break
136             s = buf.split()
137             if s and s[0][-1] == ':':
138                 a=int(s[0][:-1],16)
139                 if a != count:
140                     print "Format error: %x != %x"%(a,count)
141                     sys.exit(2)
142                 count += 16
143                 f.write(binascii.a2b_hex(string.join(s[1:],'')))
144         tn.read_until(">",1)
145
146     f.close()
147     if verbose:
148         print ""
149
150 def telnet_option(sock,cmd,option):
151     #print "Option: %d %d" % (ord(cmd), ord(option))
152     if cmd == telnetlib.DO:
153         c=telnetlib.WILL
154     elif cmd == telnetlib.WILL:
155         c=telnetlib.DO
156     sock.sendall(telnetlib.IAC + c + option)
157
158 def telnet_timeout():
159     print "Fatal error: telnet timeout!"
160     sys.exit(1)
161
162 def usage():
163     print __doc__ % os.path.basename(sys.argv[0])
164
165 ####################
166
167 try:
168     opts, args = getopt.getopt(sys.argv[1:], "hdf:qp:P:rvV", \
169         ["help", "dump", "file=", "user=", "pass=", "port=",
170          "quiet=", "reboot", "verbose", "version"])
171 except getopt.GetoptError:
172     # print help information and exit:
173     usage()
174     sys.exit(1)
175
176 for o, a in opts:
177     if o in ("-h", "--help"):
178         usage()
179         sys.exit(1)
180     elif o in ("-V", "--version"):
181         print "%s: 0.11" % sys.argv[0]
182         sys.exit(1)
183     elif o in ("-d", "--no-dump"):
184         do_dump = 1
185     elif o in ("-f", "--file"):
186         dumpfile = a
187     elif o in ("-u", "--user"):
188         user = a
189     elif o in ("-p", "--pass"):
190         password = a
191     elif o == "--port":
192         PORT = int(a)
193     elif o in ("-q", "--quiet"):
194         verbose = 0
195     elif o in ("-r", "--reboot"):
196         reboot = 1
197     elif o in ("-v", "--verbose"):
198         verbose = 1
199
200 # make sure we have enough arguments
201 if len(args) > 0:
202     HOST = args[0]
203
204 if len(args) == 2:
205     if args[1].split(':')[0] in ("tftp", "http", "ftp"):
206         url = args[1]
207     else:
208         imagefile = args[1]
209 else:
210     do_dump = 1;
211
212 ####################
213 # create a telnet session to the router
214 try:
215     tn = telnetlib.Telnet(HOST)
216 except socket.error, msg:
217     print "Unable to establish telnet session to %s: %s" % (HOST, msg)
218     sys.exit(1)
219
220 tn.set_option_negotiation_callback(telnet_option)
221
222 buf = tn.read_until("Username: ", 3)
223 if not buf:
224     telnet_timeout()
225 tn.write(user+"\n")
226 if password:
227     buf = tn.read_until("Password: ", 3)
228     if not buf:
229         telnet_timeout()
230     tn.write(password+"\n")
231
232 # wait for prompt
233 buf = tn.read_until("> ", 3)
234 if not buf:
235     telnet_timeout()
236
237 flashsize = get_flash_size()
238
239 if do_dump:
240     image_dump(tn, dumpfile)
241
242 if imagefile or url:
243     splitpath = os.path.split(imagefile)
244
245     # create load command
246     if url:
247         cmd = "load -u %s -r 0\n" % (url)
248     else:
249         server = tn.get_socket().getsockname()[0]
250         cmd = "load -u http://%s:%d/%s -r 0\n" % (server, PORT, splitpath[1])
251
252         if not os.access(imagefile, os.R_OK):
253             print "File access error: %s" % (imagefile)
254             sys.exit(3)
255
256         # make sure we're in the directory where the image is located
257         if splitpath[0]:
258             os.chdir(splitpath[0])
259
260         start_server(server)
261
262     if verbose:
263         print "Unlocking flash..."
264     tn.write("unlock 0 0x%x\n" % flashsize)
265     buf = tn.read_until("Returned 0",5)
266
267     if verbose:
268         print "Writing new image..."
269     print cmd,
270     tn.write(cmd)
271     buf = tn.read_until("Returned 0",10)
272
273     # wait till the transfer completed
274     buf = tn.read_until("Download completed successfully",20)
275     if buf:
276         print "Flash update complete!"
277         if reboot:
278             tn.write("reboot\n")
279             print "Rebooting..."
280
281 tn.write("exit\n")
282 tn.close()
283