#!/usr/bin/python -t # -*- coding: iso-latin-1 -*- import vars import os import sys import string import bdi import time debug_level = 1 chunkfile = '/bdi/chunk.%d' % os.getpid() flash_page = 0x40000 class FlashSizeTooBig(Exception): pass class FlashError(Exception): pass def StripChunk(chunk, what='\xff'): """Löscht im Flash-Sektor 'chunk' die letzten Bytes, die den Wert 'what' haben. Normalerweise also 0xff am Ende. Wir müssen diese Bytes nicht erst brennen, da nach einem EraseFlashSector() sowieso 0xff im Sektor steht.""" n = len(chunk) while n>0: if chunk[n-1] != what: break n = n - 1 return chunk[:n] def EraseFlashSector(addr): """Löscht einen physikalischen Flash-Sektor bei Adresse 'addr'.""" if vars.get('debug') >= debug_level+1: print " x: lösche Flash-Sektor" % addr res = bdi.cmd("erase 0x%x" % addr) if string.find(res,'failed') != -1: raise FlashError, "Kann Flash bei 0xx nicht löschen" % addr def BurnFlashSector(addr,chunk,musterase=1): """Flasht einen Flash-Sektor 'chunk' physikalisch in den Flash ab Adresse 'addr'""" chunk = StripChunk(chunk) if len(chunk)==0: # don't flash empty sectors return # Erase block if necessary if musterase: if vars.get("flash_fast"): testchunk = GetFlashSector(addr,32) testchunk = StripChunk(testchunk) if len(testchunk) > 12: EraseFlashSector(addr) else: EraseFlashSector(addr) if vars.get("flash_fast") and (len(chunk) == 12): # we've been asked to not burn empty sectors return fname = vars.get('tftpboot')+chunkfile try: # Create a file that is accessible for the TFTP daemon and the BDI 2000 f = open(fname,'wb') f.write(chunk) f.close() os.chmod(vars.get('tftpboot')+chunkfile, 0666) # Burn chunk of data into flash if vars.get('debug') >= debug_level+1: print " x: brenne %d Bytes ins Flash" % (addr, len(chunk)) res = bdi.cmd("prog 0x%x %s BIN" % (addr, chunkfile)) finally: os.unlink(fname) if string.find(res,'failed') != -1: raise FlashError,"Flashen schlug fehl bei 0xx" % addr def GetFlashSector(addr,size): if vars.get('debug') >= debug_level+1: print " x: lade %d Bytes von Flash" % (addr, size) # Create a world-writable file that the TFTP daemon and bdi2000 can write to f = open(vars.get('tftpboot')+chunkfile,'wb') f.close() os.chmod(vars.get('tftpboot')+chunkfile, 0666) # Place memory dump into file res = bdi.cmd("dump 0x%x 0x%x %s" % (addr, size,chunkfile) ) if string.find(res,'failed') != -1: raise FlashError, "Lesen vom Flash schlug fehl bei x" % addr # Read file and delete it f = open(vars.get('tftpboot')+chunkfile,'rb') chunk = f.read() f.close() os.unlink(vars.get('tftpboot')+chunkfile) return chunk def CompareFlash(addr,chunk): chunk = '\xff' # Memory-Bereich überprüfen if len(chunk) >= 64: chunk2 = bdi.getmem(addr, 64) if chunk[:64] != chunk2: return 1 # Compare Checksum s = "mc 0x%x %d" % (addr, len(chunk)) print s s = bdi.cmd(s) s = s[:-2] print s csum = 0 for c in chunk: csum = csum + ord(c) print "%x" % csum # Compare full sector # XXX def BurnFileToFlash(addr, file, maxsize=None): f = open(file, 'rb') totalsize = os.stat(file).st_size if vars.get('debug') >= debug_level: print " Image:", file print " Bytes:", totalsize print " Max: ", maxsize if maxsize and totalsize>maxsize: raise FlashSizeTooBig count = 0 starttime = time.time() while 1: chunk = StripChunk(f.read(flash_page)) if len(chunk)==0: break if vars.get('flash_compare'): if vars.get('debug') >= debug_level: t = time.time()-starttime if count == 0: print " x: bereits geflasht? %0.1f %%" % (addr,count*100.0/totalsize) else: print " x: bereits geflasht? %0.1f %% - %.1f Sekunden" % (addr,count*100.0/totalsize, t) # First read 64 characters chunk2 = StripChunk(bdi.getmem(addr, 64)) if chunk[:len(chunk2)]==chunk2: # then read whole page chunk2 = StripChunk(GetFlashSector(addr,len(chunk))) if chunk==chunk2: if vars.get('debug') >= debug_level: print " x: bereits geflasht!" % addr addr = addr + flash_page count = count + flash_page continue else: if vars.get('debug') >= debug_level: t = time.time()-starttime if count == 0: print " x: %0.1f %%" % (addr, count*100/totalsize) else: print " x: %0.1f %% - %.1f Sekunden" % (addr,count*100.0/totalsize, t) chunk2 = "need_erase" BurnFlashSector(addr, chunk, chunk2 != "") addr = addr + flash_page count = count + flash_page def GetFileFromFlash(addr, size, file, strip=1): if vars.get('debug') >= debug_level: print " Destination:", file print " Max bytes: ", size # Create a world-writable file that the TFTP daemon and bdi2000 can write to outf = open(file,'wb') starttime = time.time() count = 0 while count < size: if vars.get('debug') >= debug_level: t = time.time()-starttime if count == 0: print " x: %0.1f %%" % (addr, count*100/size) else: print " x: %0.1f %% - %.1f Sekunden" % (addr,count*100.0/size, t) chunk = GetFlashSector(addr, flash_page) addr = addr + flash_page count = count + flash_page if strip and (count == size): chunk = StripChunk(chunk) outf.write(chunk) outf.close() if __name__ == '__main__': def usage(lvl=1, txt=''): if txt != '': print txt print "Usage: burner.py
" print " burner.py /tftpboot/zImage 0x40000" sys.exit(1) vars.load() import getopt try: opts, args = getopt.getopt(sys.argv[1:], "hN", ["help", "nocompare"]) except getopt.GetoptError: # print help information and exit: usage(1) output = None for o, a in opts: if o in ("-h", "--help"): usage(0) if o in ("-N", "--nocompare"): vars.set('flash_compare', 0) if len(args) < 2: usage(1, 'missing arguments') file = args[0] if file=='': usage(1,'Erstes Argument muß eine Datei sein') # Check and normalize load address addr = args[1] if addr=='': usage(1,'Zweites Argument muß eine Hexadezimalzahl sein') if addr[0:2] == '0x': addr = addr[2:] try: addr = int(addr,16) except: usage(1,'Zweites Argument muß eine Hexadezimalzahl sein') if addr % flash_page != 0: usage(1, "Zieladresse muß Vielfaches von %x sein" % flash_page) vars.set('flash_compare',0) BurnFileToFlash(addr, file)