def start_upgrade(self, client): # ask for a filename (must have already downloaded it) mw = get_parent_main_window(self) dev = client.dev fileName = mw.getOpenFileName("Select upgraded firmware file", "*.dfu") if not fileName: return from ckcc.utils import dfu_parse from ckcc.sigheader import FW_HEADER_SIZE, FW_HEADER_OFFSET, FW_HEADER_MAGIC from ckcc.protocol import CCProtocolPacker from hashlib import sha256 import struct try: with open(fileName, 'rb') as fd: # unwrap firmware from the DFU offset, size, *ignored = dfu_parse(fd) fd.seek(offset) firmware = fd.read(size) hpos = FW_HEADER_OFFSET hdr = bytes(firmware[hpos:hpos + FW_HEADER_SIZE]) # needed later too magic = struct.unpack_from("<I", hdr)[0] if magic != FW_HEADER_MAGIC: raise ValueError("Bad magic") except Exception as exc: mw.show_error( "Does not appear to be a Coldcard firmware file.\n\n%s" % exc) return # TODO: # - detect if they are trying to downgrade; aint gonna work # - warn them about the reboot? # - length checks # - add progress local bar mw.show_message( "Ready to Upgrade.\n\nBe patient. Unit will reboot itself when complete." ) def doit(): dlen, _ = dev.upload_file(firmware, verify=True) assert dlen == len(firmware) # append the firmware header a second time result = dev.send_recv( CCProtocolPacker.upload(size, size + FW_HEADER_SIZE, hdr)) # make it reboot into bootlaoder which might install it dev.send_recv(CCProtocolPacker.reboot()) self.thread.add(doit) self.close()
def receive_list_menu(self, menu, addr): window = get_parent_main_window(menu) menu.addAction(_("Send via e-mail"), lambda: self.send(window, addr))