示例#1
0
def verify(ser, path, flashsize, bootloadersize, destructive=False):
    try:
        f = open(path, "rb")
    except IOError:
        CHK(False, "'%s': can't open file" % path, 5)
    data = f.read()

    f.close()
    modem = XMODEM(None, None)

    if destructive:
        ser.write('v')
        #no prefixed bytes, since uploading a bootloader
        bootloadersize = 0x0000
    else:
        ser.write('c')

    lines = []
    resp = ""
    while len(lines) < 3:
        resp += get_response(ser)
        lines = resp.split('\r\n')
    CHK(lines[1].startswith("CRC:"), RESP_ERR, 3)
    testcrc = lines[1][9:]

    crc = int(modem.calc_crc(data))
    # rest of the flash is 0xFF
    for i in xrange(flashsize - len(data) - bootloadersize):
        crc = modem.calc_crc('\xFF', crc)

    crc = hex(crc)[2:].upper()
    #extend to 4 chars
    crc = (4 - len(crc)) * "0" + crc
    print "CRC", crc, testcrc
    if testcrc == crc:
        INFO("Verify OK!")
    return testcrc == crc
示例#2
0
def verify(ser, path, flashsize, bootloadersize, destructive=False):
    try:
        f = open(path, "rb")
    except IOError:
        CHK(False, "'%s': can't open file" % path, 5)
    data = f.read()

    f.close()
    modem = XMODEM(None, None)

    if destructive:
        ser.write("v")
        # no prefixed bytes, since uploading a bootloader
        bootloadersize = 0x0000
    else:
        ser.write("c")

    lines = []
    resp = ""
    while len(lines) < 3:
        resp += get_response(ser)
        lines = resp.split("\r\n")
    CHK(lines[1].startswith("CRC:"), RESP_ERR, 3)
    testcrc = lines[1][9:]

    crc = int(modem.calc_crc(data))
    # rest of the flash is 0xFF
    for i in xrange(flashsize - len(data) - bootloadersize):
        crc = modem.calc_crc("\xFF", crc)

    crc = hex(crc)[2:].upper()
    # extend to 4 chars
    crc = (4 - len(crc)) * "0" + crc
    print "CRC", crc, testcrc
    if testcrc == crc:
        INFO("Verify OK!")
    return testcrc == crc
示例#3
0
class MtkFlasher(object):
    BAUD = {
        "ls": 115200,
        "hs": 921600,
        "ss": 3000000,
    }
    MAGIC = 0x00052001
    SECRET_MAGIC = 0x00052002

    def __init__(self, port, speed, binpath=None, debug=False):
        self.speed = speed
        self.baud = self.BAUD[speed]
        self.port = port
        self.xm = XMODEM(self.getc, self.putc, "xmodem1k", "\xff")
        self.binpath = binpath or BIN_PATH
        self.tag = 0x1000
        self.debug = debug

    def log(self, *args):
        if self.debug:
            print(*args)

    def getc(self, size, timeout=1):
        self.ser.timeout = timeout
        return self.ser.read(size)

    def putc(self, data, timeout=1):
        self.ser.write_timeout = timeout
        return self.ser.write(data)

    def xm_send(self, fd, msg="  Sending"):
        fd.seek(0, 2)
        length = fd.tell()
        fd.seek(0, 0)
        blocks = (length + 1023) / 1024

        def callback(total, success, error):
            sys.stdout.write("\r%s... %d%%" % (msg, 100 * success // blocks))
            sys.stdout.flush()

        self.xm.send(fd, callback=callback)
        print()

    def bootstrap(self, ):
        print("Opening port at 115200 baud...")
        self.ser = Serial(self.port, 115200)
        fname = "uart_%s.bin" % self.speed
        print("Sending baudrate switcher (%s)..." % fname)
        self.xm_send(open(os.path.join(self.binpath, fname), "rb"))
        self.ser.close()

        print("Reopening port at %d baud..." % self.baud)
        self.ser = Serial(self.port, self.baud)
        fname = "ated_%s.bin" % self.speed
        print("Sending ATED (%s)..." % fname)
        self.xm_send(open(os.path.join(self.binpath, fname), "rb"))

    def command(self, cmd, args=b"", magic=MAGIC):
        self.tag += 1
        self.ser.timeout = 5
        self.ser.write_timeout = 5

        payload = struct.pack(">H", cmd) + args
        data = struct.pack(">IHH", magic,
                           len(payload) + 2, self.tag) + payload
        crc = self.xm.calc_crc(data)
        self.ser.write(data + struct.pack(">H", crc))

        reply = self.ser.read(8)
        reply_magic, reply_len, tag = struct.unpack(">IHH", reply)
        assert reply_magic == (magic | 0x80000000)
        assert tag == self.tag
        reply += self.ser.read(reply_len)
        assert len(reply) == reply_len + 8
        crc = struct.unpack(">H", reply[-2:])[0]
        assert self.xm.calc_crc(reply[:-2]) == crc
        reply_cmd = struct.unpack(">H", reply[8:10])[0]
        assert reply_cmd == (cmd + 1)
        return reply[10:-2]

    def initialize(self):
        self.log("  cmd: initialize")
        reply = self.command(0x00)
        self.log("    returned:", reply.encode("hex"))

    def get_storage_info(self):
        self.log("  cmd: get_storage_info")
        reply = self.command(0x10)
        self.log("    returned:", reply.encode("hex"))

        unk1, unk2, flash_size, = struct.unpack(">III", reply)
        return {"size": flash_size}

    def erase(self, start, length):
        self.log("  cmd: erase(0x%x, 0x%x)" % (start, length))
        reply = self.command(0x0a, struct.pack(">II", start, length))
        self.log("    returned:", reply.encode("hex"))

    def erase_end(self):
        self.log("  cmd: erase_end")
        reply = self.command(0x0c)
        self.log("    returned:", reply.encode("hex"))

    def download(self, address, length):
        self.log("  cmd: download(0x%x, 0x%x)" % (address, length))
        flags = 0x01000400
        reply = self.command(0x02, struct.pack(">IIII",
                                               address, length,
                                               address + length, flags))
        self.log("    returned:", reply.encode("hex"))

    def download_end(self):
        self.log("  cmd: download_end")
        reply = self.command(0x04)
        self.log("    returned:", reply.encode("hex"))

    # Orig uses 0x20000 but this provides more granular progress
    def erase_range(self, addr, length, blocksize=0x2000):
        for i in xrange(0, length, blocksize):
            self.erase(addr + i, min(blocksize, length - i))
            if not self.debug:
                sys.stdout.write("\r  Erasing... %d%%" % (100 * i // length))
                sys.stdout.flush()
        self.erase_end()
        if not self.debug:
            print("\r  Erasing... 100%")

    def write_file(self, addr, filename, erase=True):
        print("Writing to 0x%x: %s" % (addr, filename))
        fd = open(filename, "rb")
        fd.seek(0, 2)
        length = fd.tell()
        fd.seek(0, 0)

        assert addr & 0xfff == 0
        padded_length = (length + 0xfff) & ~0xfff

        if erase:
            self.erase_range(addr, padded_length)

        self.download(addr, length)
        self.xm_send(fd, "  Writing")
        self.download_end()

    def read_efuse(self, off, length):
        assert (off & 0xf == 0)
        assert (length & 0xf == 0)
        self.log("  cmd: read_efuse")
        reply = self.command(0x04, struct.pack(">II", off, length),
                             self.SECRET_MAGIC)
        self.log("    returned:", reply.encode("hex"))
        return reply[4:]

    def read_unique_id(self):
        self.log("  cmd: read_unique_id")
        reply = self.command(0x02, magic=self.SECRET_MAGIC)
        self.log("    returned:", reply.encode("hex"))
        return reply[4:]

    def get_mac(self):
        fuseblock = self.read_efuse(0, 0x10)
        return ":".join("%02x" % ord(c) for c in fuseblock[4:10])