Démarche flash Neufbox v4
This commit is contained in:
commit
0604556c8d
34
NeufBoxV4/README.md
Normal file
34
NeufBoxV4/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#Neufbox V4
|
||||||
|
|
||||||
|
https://openwrt.org/toh/sfr/nb4 [https://openwrt.org/toh/sfr/nb4]
|
||||||
|
|
||||||
|
La neufbox v4 se flashe bien. il faut préparer l'image et invoquer le script flashimage ( pas de moi, mais le lien est mort. Je ne connais pas la licence ...)
|
||||||
|
|
||||||
|
## A savoir :
|
||||||
|
Si vous voulez utiliser le wifi, il faut utiliser l'image de chaos calmer et indiquer l'adresse mac materielle de la carte wifi dans `/etc/config/wifi` une fois flashée. Pendant le flash, l'adresse mac est aussi annoncée par le script. Bien veiller à ce que ce soit celle de la box et non pas du P.C.
|
||||||
|
|
||||||
|
Si vous voulez vous passer du wifi, vous pouvez utiliser la version 19.07, je l'ai testée avec du partage de connexion USB : https://openwrt.org/docs/guide-user/network/wan/smartphone.usb.tethering [https://openwrt.org/docs/guide-user/network/wan/smartphone.usb.tethering] et ça me semble très bien fonctionner.
|
||||||
|
|
||||||
|
## Préparation de l'image
|
||||||
|
|
||||||
|
On télécharge l'image .bin sur le site d'openwrt, en faisant attention a la référence de la box (FXC ou SER ) puis :
|
||||||
|
|
||||||
|
```
|
||||||
|
cat /dev/zero | tr '\000' '\377' | dd bs=64k of=nb4-openwrt count=128 seek=0
|
||||||
|
dd bs=64k of=nb4-openwrt if=image-du-site-openwrt.bin seek=1
|
||||||
|
dd bs=64k of=nb4-openwrt if=/dev/zero count=1 seek=127
|
||||||
|
```
|
||||||
|
|
||||||
|
Cela permet, comme décrit en commentaire au début du script, d'outrepasser le bootloader et d'installer l'image système. La box s'attend a une image d'une taille précise (8Mb), donc il faut aussi finaliser avec des 0.
|
||||||
|
|
||||||
|
## Le flash
|
||||||
|
|
||||||
|
Il faut brancher la machine avec le script flashimage et l'image. Il faut connaitre l'interface réseau, être root et disposer de python2. Pour trouver l'interface réseau de votre P.C. : `ip address`. Le début de ligne doit être en eth[numéro] ou enp[numéro+chosesderrièreoupas]
|
||||||
|
|
||||||
|
une fois cela trouvé, en tant que root ou avec sudo :
|
||||||
|
```
|
||||||
|
./flashimage.py eth0 nb4-openwrt
|
||||||
|
```
|
||||||
|
Il faut démarrer la box en appuyant sur le bouton reset ( ou le bouton/facade SFR selon le modèle ) et brancher le cable de votre P.C. au port TV de la box.
|
||||||
|
|
||||||
|
|
326
NeufBoxV4/flashimage.py
Normal file
326
NeufBoxV4/flashimage.py
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# may 2009 (c) avd <avd@patatrac.info>
|
||||||
|
|
||||||
|
"""
|
||||||
|
flashimage for nb4
|
||||||
|
|
||||||
|
Easily flash an nb4 with an full image of 8MB
|
||||||
|
and a network connection.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
./flashimage.py <network interface> <full image>
|
||||||
|
|
||||||
|
The nb4 need to be in download mode (press service button
|
||||||
|
approximately 5 seconds when box booting until it is
|
||||||
|
blinking blue).
|
||||||
|
|
||||||
|
This program uses the download mode of the CFE soft
|
||||||
|
for the NB4 box. This program send request for flashing
|
||||||
|
all the flash AFTER the CFE part.
|
||||||
|
Obviously, you can use it without risking to destroy your
|
||||||
|
nb4 box because there will be the CFE to recover.
|
||||||
|
|
||||||
|
this program remove all the things after CFE. Think to save your config before use it.
|
||||||
|
|
||||||
|
This program expect a full image of 8MB (CFE + MAIN + JFFS2 + RESCUE + DSL + NV) but the CFE soft on the nb4 in download mode and without EALL request jump the first 64KB of the image (CFE part) thus does not write the CFE part on the flash.
|
||||||
|
So, if you don't have the CFE part and you want build a full image, you can remplace the 64KB of the beginning of the full image by any data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import string
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
# defs
|
||||||
|
ETH_ADDR_BROADCAST = '\xff\xff\xff\xff\xff\xff'
|
||||||
|
|
||||||
|
CMD_VERSION = 0x0000
|
||||||
|
CMD_REQUEST = 0x0001
|
||||||
|
CMD_DATA = 0x0002
|
||||||
|
CMD_RESET = 0x0003
|
||||||
|
CMD_VERIFY = 0x0004
|
||||||
|
|
||||||
|
# based on http://dev.efixo.net/browser/trunk/openwrt/target/linux/brcm63xx/files-2.6.21/include/asm-mips/mach-bcm63xx/nb4/box/partition.h
|
||||||
|
# mapping for 2.x (not used for now)
|
||||||
|
NB_CFE_OFFSET = 0x0
|
||||||
|
NB_CFE_SIZE = 65536
|
||||||
|
|
||||||
|
NB_MAIN_OFFSET = NB_CFE_OFFSET + NB_CFE_SIZE
|
||||||
|
NB_MAIN_SIZE = 5570560
|
||||||
|
|
||||||
|
NB_JFFS2_OFFSET = NB_MAIN_OFFSET + NB_MAIN_SIZE
|
||||||
|
NB_JFFS2_SIZE = 655360
|
||||||
|
|
||||||
|
NB_RESCUE_OFFSET = NB_JFFS2_OFFSET + NB_JFFS2_SIZE
|
||||||
|
NB_RESCUE_SIZE = 1572864
|
||||||
|
|
||||||
|
NB_DSL_OFFSET = NB_RESCUE_OFFSET + NB_RESCUE_SIZE
|
||||||
|
NB_DSL_SIZE = 458752
|
||||||
|
|
||||||
|
NB_NV_OFFSET = NB_DSL_OFFSET + NB_DSL_SIZE
|
||||||
|
NB_NV_SIZE = 65535
|
||||||
|
|
||||||
|
NB_TOTAL_SIZE = 8388608
|
||||||
|
|
||||||
|
counter_wsequence = 0x2300
|
||||||
|
|
||||||
|
class Dlcpkt:
|
||||||
|
'''dlc packet - stock values in network order'''
|
||||||
|
dstaddr = None
|
||||||
|
srcaddr = None
|
||||||
|
sap = None
|
||||||
|
wcmd = None
|
||||||
|
wsequence = None
|
||||||
|
woffset = None
|
||||||
|
wsegment = None
|
||||||
|
wlen = None
|
||||||
|
bdata = None
|
||||||
|
|
||||||
|
hdr_len = 24
|
||||||
|
data_len = 24
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.bzero()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.dstaddr + self.srcaddr + self.sap + self.wcmd + self.wsequence + self.woffset + self.wsegment + self.wlen + self.bdata
|
||||||
|
|
||||||
|
def bzero(self):
|
||||||
|
self.dstaddr = '\x00\x00\x00\x00\x00\x00'
|
||||||
|
self.srcaddr = '\x00\x00\x00\x00\x00\x00'
|
||||||
|
self.sap = '\x88\x88'
|
||||||
|
self.wcmd = '\x00\x00'
|
||||||
|
self.wsequence = '\x00\x00'
|
||||||
|
self.woffset = '\x00\x00'
|
||||||
|
self.wsegment = '\x00\x00'
|
||||||
|
self.wlen = '\x00\x00'
|
||||||
|
self.bdata = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
return self.str()
|
||||||
|
|
||||||
|
def unpack(self, data):
|
||||||
|
self.dstaddr = data[:6]
|
||||||
|
self.srcaddr = data[6:12]
|
||||||
|
self.sap = data[12:14]
|
||||||
|
self.wcmd = data[14:16]
|
||||||
|
self.wsequence = data[16:18]
|
||||||
|
self.woffset = data[18:20]
|
||||||
|
self.wsegment = data[20:22]
|
||||||
|
self.wlen = data[22:24]
|
||||||
|
self.bdata = data[24:]
|
||||||
|
|
||||||
|
def eth_ntoa(raw):
|
||||||
|
# Convert binary data into a string.
|
||||||
|
return ":".join(["%02X" % (ord(ch),) for ch in raw])
|
||||||
|
|
||||||
|
def eth_aton(buffer):
|
||||||
|
addr =''
|
||||||
|
temp = string.split(buffer,':')
|
||||||
|
buffer = string.join(temp,'')
|
||||||
|
# Split up the hex values and pack.
|
||||||
|
for i in range(0, len(buffer), 2):
|
||||||
|
addr = ''.join([addr,struct.pack('>B', int(buffer[i: i + 2], 16))],)
|
||||||
|
return addr
|
||||||
|
|
||||||
|
def i16ton(i16):
|
||||||
|
''' Convert 16 bit integer to network '''
|
||||||
|
raw = struct.pack('H', i16)
|
||||||
|
return raw
|
||||||
|
|
||||||
|
def hex2dec(hex):
|
||||||
|
return int(hex, 16)
|
||||||
|
|
||||||
|
def dec2hex(dec):
|
||||||
|
return "%X" % n
|
||||||
|
|
||||||
|
def request(s, dlcpkt):
|
||||||
|
s.send(str(dlcpkt))
|
||||||
|
|
||||||
|
resp = s.recv(48);
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def send_file(s, dlcpkt_w, file):
|
||||||
|
global counter_wsequence
|
||||||
|
progress_list = [ '|', '/', '-', '\\' ]
|
||||||
|
progress_index = 0
|
||||||
|
wsegment_h = 0x0000
|
||||||
|
woffset_h = 0x0000
|
||||||
|
counter = 1
|
||||||
|
|
||||||
|
dlcpkt_r = Dlcpkt()
|
||||||
|
dlcpkt_w.wcmd = i16ton(CMD_DATA)
|
||||||
|
|
||||||
|
buf_len = 0x0200
|
||||||
|
|
||||||
|
filesize = os.path.getsize(file)
|
||||||
|
|
||||||
|
f = open(file, "r")
|
||||||
|
|
||||||
|
print ' > send %s (size=%d)' % (file, filesize)
|
||||||
|
print ' (please wait while the box erasing the flash from 0x00010000 to 0x007fffff before flashing ...)'
|
||||||
|
|
||||||
|
block = f.read(buf_len)
|
||||||
|
while block != '':
|
||||||
|
dlcpkt_w.bdata = block
|
||||||
|
dlcpkt_w.wsequence = i16ton(counter_wsequence)
|
||||||
|
dlcpkt_w.wlen = i16ton(len(block))
|
||||||
|
dlcpkt_w.wsegment = i16ton(wsegment_h)
|
||||||
|
dlcpkt_w.woffset = i16ton(woffset_h)
|
||||||
|
|
||||||
|
s.send(str(dlcpkt_w))
|
||||||
|
|
||||||
|
# check
|
||||||
|
resp = s.recv(48);
|
||||||
|
dlcpkt_r.unpack(resp)
|
||||||
|
|
||||||
|
if dlcpkt_r.wsequence != dlcpkt_w.wsequence:
|
||||||
|
print 'FAILED.'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
sys.stdout.write('\r' + progress_list[progress_index] + " %02.f%%" % ( ((counter * len(block)) / (filesize * 1.0)) * 100 ))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
progress_index = (progress_index + 1) % len(progress_list)
|
||||||
|
|
||||||
|
### INCR ###
|
||||||
|
# final address = segment<<4 + offset
|
||||||
|
wsegment_h = (wsegment_h + (len(block)/0x10)) % (0x10000)
|
||||||
|
woffset_h = (wsegment_h & 0x000f)
|
||||||
|
|
||||||
|
counter_wsequence = (counter_wsequence + 1) % (0x10000)
|
||||||
|
counter = counter + 1
|
||||||
|
|
||||||
|
# new read
|
||||||
|
block = f.read(buf_len)
|
||||||
|
|
||||||
|
# don't be too speedy
|
||||||
|
time.sleep(0.002)
|
||||||
|
|
||||||
|
print ' '
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
###### MAIN ######
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print 'Usage: %s <network interface> <full image>' % (sys.argv[0])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# stock args
|
||||||
|
dev = sys.argv[1]
|
||||||
|
firm = sys.argv[2]
|
||||||
|
|
||||||
|
# check firmware first
|
||||||
|
try:
|
||||||
|
firmsize = os.path.getsize(firm)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("%s\n" % (str(e)));
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if firmsize > NB_TOTAL_SIZE:
|
||||||
|
sys.stderr.write("Error, The size of the firmware should not exceed %d bytes otherwise the CFE might be compromised (%s - %d bytes)\n" % (NB_TOTAL_SIZE, firm, firmsize));
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if firmsize != NB_TOTAL_SIZE:
|
||||||
|
print 'This program expects a full image of %d bytes (CFE + MAIN + JFFS2 + RESCUE + DSL + NV)' % (NB_TOTAL_SIZE,)
|
||||||
|
print 'Your image has a size of %d bytes' % (firmsize)
|
||||||
|
ch = raw_input('Continue anyway ? (if you do not know what you do, do not continue !) (y|N) ')
|
||||||
|
if ch != 'y':
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
print '+++++++++++++++++++++++++++++++++++++++++++++++'
|
||||||
|
print ' Image: %s' % (firm)
|
||||||
|
print ' > Size: %d bytes' % (firmsize,)
|
||||||
|
print '+++++++++++++++++++++++++++++++++++++++++++++++'
|
||||||
|
|
||||||
|
# open socket RAW
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Error while creating socket: %s\n" % str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# bind on device
|
||||||
|
s.bind((dev,0x8888))
|
||||||
|
|
||||||
|
# get the mac addr
|
||||||
|
my_eth_addr_r = s.getsockname()[-1]
|
||||||
|
|
||||||
|
print "%s ethernet address: %s" % (dev, eth_ntoa(my_eth_addr_r))
|
||||||
|
|
||||||
|
# write and read packet
|
||||||
|
dlcpkt_w = Dlcpkt()
|
||||||
|
dlcpkt_r = Dlcpkt()
|
||||||
|
|
||||||
|
# first send discover to get MAC ADDR
|
||||||
|
# and VERSION_INFO of the box
|
||||||
|
print " > Info request on broadcast"
|
||||||
|
|
||||||
|
dlcpkt_w.dstaddr = ETH_ADDR_BROADCAST
|
||||||
|
dlcpkt_w.srcaddr = my_eth_addr_r
|
||||||
|
dlcpkt_w.wcmd = i16ton(CMD_VERSION)
|
||||||
|
|
||||||
|
resp = request(s, dlcpkt_w)
|
||||||
|
dlcpkt_r.unpack(resp)
|
||||||
|
|
||||||
|
print " < Receive response from %s - %s" % (eth_ntoa(dlcpkt_r.srcaddr), dlcpkt_r.bdata[4:])
|
||||||
|
|
||||||
|
box_eth_addr_r = dlcpkt_r.srcaddr
|
||||||
|
|
||||||
|
ch = raw_input('Continue ? (y|N) ')
|
||||||
|
if ch != 'y':
|
||||||
|
print "Ok, exit !"
|
||||||
|
s.close()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# ask we want to put a firmware
|
||||||
|
print " > Flash request to %s" % (eth_ntoa(box_eth_addr_r))
|
||||||
|
|
||||||
|
dlcpkt_w.dstaddr = box_eth_addr_r
|
||||||
|
dlcpkt_w.wcmd = i16ton(CMD_REQUEST)
|
||||||
|
dlcpkt_w.wsequence = i16ton(counter_wsequence)
|
||||||
|
|
||||||
|
resp = request(s, dlcpkt_w)
|
||||||
|
dlcpkt_r.unpack(resp)
|
||||||
|
|
||||||
|
if dlcpkt_r.wcmd == i16ton(CMD_REQUEST) \
|
||||||
|
and dlcpkt_r.wsequence == dlcpkt_w.wsequence :
|
||||||
|
print " < Ok, box wait flashing"
|
||||||
|
else:
|
||||||
|
print " < Error on flash request ..."
|
||||||
|
s.close()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
counter_wsequence = (counter_wsequence + 1) % (0x10000)
|
||||||
|
|
||||||
|
# send the firmware
|
||||||
|
send_file(s, dlcpkt_w, firm);
|
||||||
|
|
||||||
|
dlcpkt_w.bzero()
|
||||||
|
dlcpkt_w.dstaddr = box_eth_addr_r
|
||||||
|
dlcpkt_w.srcaddr = my_eth_addr_r
|
||||||
|
|
||||||
|
# verify ?
|
||||||
|
|
||||||
|
# reboot the box ?
|
||||||
|
ch = raw_input('Press Enter to reboot the box')
|
||||||
|
print " > Send reboot request"
|
||||||
|
|
||||||
|
dlcpkt_w.wcmd = i16ton(CMD_RESET)
|
||||||
|
resp = request(s, dlcpkt_w);
|
||||||
|
dlcpkt_r.unpack(resp)
|
||||||
|
|
||||||
|
if dlcpkt_r.wcmd == i16ton(CMD_RESET):
|
||||||
|
print " < Ok, rebooting the box"
|
||||||
|
else:
|
||||||
|
print " > Error on rebooting command"
|
||||||
|
|
||||||
|
print "End."
|
||||||
|
|
||||||
|
s.close()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user