#!/usr/bin/env python2 """ Aufruf: ./dtprog.py [-d /dev/ttyXXX] [-b ] bootROM, a very small bootloader for $NAME protocol details: abbrv: H = Host, CPU = C value/cmd | direction | comment ------------------------------------------------------------ 'H' | H -> C | enter bootROM ("HI") 'O' | C -> H | ack bootROM entry ("OH HAI") 'W'0xZZZZZZZZ0xYYYYYYYY| H -> C | write instr (0xYY...Y) to | address (0xZZ...Z) 'D' | C -> H | instr write done 'R'0xZZZZZZZZ | H -> C | read instr from address (0xZZ..Z) 'F'0xYYYYYYYY | C -> H | instr read done and return instr 'Q'0xZZZZZZZZ0xYYYYYYYY| H -> C | write data (0xYY...Y) to | address (0xZZ...Z) 'A' | C -> H | data write done 'T'0xZZZZZZZZ | H -> C | read data from address (0xZZ..Z) 'G'0xYYYYYYYY | C -> H | read done and return data 'J'0xZZZZZZZZ | H -> C | jump to address (0xZZ...Z) """ import sys, time from SerialPort_linux import SerialPort, SerialPortException SPLIT = 30 class RAMSequence(object): def __init__(self, type, address, data): self.type = type self.addr = address self.data = data def sendbyte(byte): """ send a byte to the TTY-device """ tty.write(chr(byte)) def sendword(word): """ send a word to the TTY-device """ sendbyte(word & 0xFF) sendbyte((word >> 8) & 0xFF) def senddword(dword): """ send a dword to the TTY-device """ sendbyte((dword >> 24) & 0xFF) sendbyte((dword >> 16) & 0xFF) sendbyte((dword >> 8) & 0xFF) sendbyte(dword & 0xFF) def recvbyte(): """ receive a byte from the TTY-device """ return ord(tty.read()) def recvword(): return (recvbyte() << 24) & (recvbyte() << 16) & (recvbyte() << 8) & recvbyte() def bootromexec(): sendbyte(0x4a) # 'J' def brwriteinstr(address, data): """ send a WRITE-command (instr) to the bootROM-firmware """ # send WRITE instr command sendbyte(0x57) # 'W' # time.sleep(0.01) if (recvbyte() != 0x57): # 'W' print "host: write instr fail (1)" raise Exception senddword(address) senddword(data) time.sleep(0.01) if (recvbyte() != 0x44): # 'D' print "host: write instr fail (2)" raise Exception def brwritedata(address, data): """ send a WRITE-command (data) to the bootROM-firmware """ # send WRITE instr command sendbyte(0x51) # 'Q' # time.sleep(0.01) if (recvbyte() != 0x51): # 'Q' print "host: write data fail (1)" raise Exception senddword(address) senddword(data) time.sleep(0.01) if (recvbyte() != 0x41): # 'A' print "host: write data fail (2)" raise Exception def readdthexfile(filename): # desired dthex filename """ proceeds a dthex file """ filep = open(filename, "r") retval = [] # returns a list of FlashSequence objects linecount = 0 for line in filep: linecount += 1 # get rid of newline characters line = line.strip() # we're only interested in 0 or 1 if line[0:1] == "0" or line[0:1] == "1": # TODO: checks... type = int(line[0:1], 10) addr = int(line[2:10], 16)/4 data = int(line[11:19], 16) # print "type: ", type, "; addr: ", hex(addr), "; data: ", hex(data) retval.append(RAMSequence(type, addr, data)) filep.close() return retval def usage(execf): """ print usage of dtprog """ print "Usage: " + execf + " [-d DEVICE] [-b BAUDRATE]" print "maybe arg-eval fail. fix the source!" def main(argv=None): """ main function of frprog """ # check command line arguments if argv is None: argv = sys.argv if len(argv) == 2 and (argv[1] == "-v" or argv[1] == "--version"): print "Version: lulz" return 0 if len(argv) != 2 and len(argv) != 4 and len(argv) != 6: usage(argv[0]) return 1 # standard baudrate baudrate = 9200 # standard serial device to communicate with device = "/dev/ttyS0" print "argv: ", argv # overrule standard device if provided with -d if len(argv) >= 4: if argv[2] == "-d": device = argv[3] else: usage(argv[0]) return 1 # overrule standard baudrate if provided with -b if len(argv) == 6: if argv[4] == "-b": baudrate = int(argv[5],10) else: usage(argv[0]) return 1 # read in data from mhx-files before starting try: ramseqs = readdthexfile(argv[1]) except IOError, error: print argv[0] + ": Error - couldn't open file " + error.filename + "!" return 1 print "Initializing serial port... (", device, ")" global tty tty = SerialPort(device, 100, baudrate) while True: tty.write('H') tty.flush() try: if tty.read() == 'O': break except SerialPortException: # timeout happened, who cares ;-) print "host: cpu in BootROM?" pass print "bootrom: OH HAI!" # save time at this point for evaluating the duration at the end starttime = time.time() time.sleep(0.1) sdots = SPLIT print "host: Transfering program to BootROM", print #TODO: remove ;) # let the fun begin! for seq in ramseqs: print "RAMing(", seq.type, ") ", hex(seq.data), " at address ", if seq.type == 1: # instruction print "", hex(seq.addr) print "host: writing instr" brwriteinstr(seq.addr, seq.data) elif seq.type == 0: # data print "", hex(seq.addr*4) print "host: writing data" brwritedata(seq.addr * 4, seq.data) tty.flush() sdots = sdots - 1 if sdots == 0: sys.stdout.write(".") sys.stdout.flush() sdots = SPLIT print bootromexec() print "Program was started. Have fun!" duration = time.time() - starttime print "Procedure complete, took", round(duration, 2), "seconds." if __name__ == '__main__': sys.exit(main())