Root/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]
12Valid 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
23If no image (or url) is given, a flash dump is created.
24A built-in http server is used when an image file is provided.
25"""
26
27import os
28import sys
29import getopt
30import getpass
31import telnetlib
32import string
33import binascii
34import socket
35import thread
36import SocketServer
37import SimpleHTTPServer
38
39reboot = 0
40HOST = "192.168.1.1"
41PORT = 8080
42user = "admin"
43#password = getpass.getpass()
44password = "password1"
45proto = "http"
46url = ""
47imagefile = ""
48dumpfile = ""
49verbose = 1
50do_dump = 0
51dumplen = 0x10000
52flashsize=4*1024*1024
53#device="br0"
54device="ixp0"
55
56####################
57
58def start_server(server):
59    httpd = SocketServer.TCPServer((server,PORT),SimpleHTTPServer.SimpleHTTPRequestHandler)
60    thread.start_new_thread(httpd.serve_forever,())
61
62####################
63
64def 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
94def 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
150def 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
158def telnet_timeout():
159    print "Fatal error: telnet timeout!"
160    sys.exit(1)
161
162def usage():
163    print __doc__ % os.path.basename(sys.argv[0])
164
165####################
166
167try:
168    opts, args = getopt.getopt(sys.argv[1:], "hdf:qp:P:rvV", \
169    ["help", "dump", "file=", "user=", "pass=", "port=",
170     "quiet=", "reboot", "verbose", "version"])
171except getopt.GetoptError:
172    # print help information and exit:
173    usage()
174    sys.exit(1)
175
176for 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
201if len(args) > 0:
202    HOST = args[0]
203
204if len(args) == 2:
205    if args[1].split(':')[0] in ("tftp", "http", "ftp"):
206        url = args[1]
207    else:
208        imagefile = args[1]
209else:
210    do_dump = 1;
211
212####################
213# create a telnet session to the router
214try:
215    tn = telnetlib.Telnet(HOST)
216except socket.error, msg:
217    print "Unable to establish telnet session to %s: %s" % (HOST, msg)
218    sys.exit(1)
219
220tn.set_option_negotiation_callback(telnet_option)
221
222buf = tn.read_until("Username: ", 3)
223if not buf:
224    telnet_timeout()
225tn.write(user+"\n")
226if 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
233buf = tn.read_until("> ", 3)
234if not buf:
235    telnet_timeout()
236
237flashsize = get_flash_size()
238
239if do_dump:
240    image_dump(tn, dumpfile)
241
242if 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
281tn.write("exit\n")
282tn.close()
283
284

Archive Download this file



interactive