def cmd_flash(device, firmware, enable_insecure, log_cb, progress_cb, complete_cb, error_cb): if firmware[0:8] not in [b"VIALFW00", b"VIALFW01"]: return error_cb("Error: Invalid signature") fw_uid = firmware[8:16] fw_ts = struct.unpack("<Q", firmware[16:24])[0] log_cb("* Firmware build date: {} (UTC)".format(datetime.datetime.utcfromtimestamp(fw_ts))) fw_hash = firmware[32:64] fw_payload = firmware[64:] if hashlib.sha256(fw_payload).digest() != fw_hash: return error_cb("Error: Firmware failed integrity check\n\texpected={}\n\tgot={}".format( fw_hash.hex(), hashlib.sha256(fw_payload).hexdigest() )) # Check bootloader is correct version send_retries(device, pad_for_vibl(b"VC\x00")) ver = device.recv(8)[0] log_cb("* Bootloader version: {}".format(ver)) if ver not in [0, 1]: return error_cb("Error: Unsupported bootloader version") send_retries(device, pad_for_vibl(b"VC\x01")) uid = device.recv(8) log_cb("* Vial ID: {}".format(uid.hex())) if uid == b"\xFF" * 8: log_cb("\n\n\n!!! WARNING !!!\nBootloader UID is not set, make sure to configure it" " before releasing production firmware\n!!! WARNING !!!\n\n") if uid != fw_uid: return error_cb("Error: Firmware package was built for different device\n\texpected={}\n\tgot={}".format( fw_uid.hex(), uid.hex() )) # OK all checks complete, we can flash now while len(fw_payload) % CHUNK != 0: fw_payload += b"\x00" # Flash log_cb("Flashing...") send_retries(device, pad_for_vibl(b"VC\x02" + struct.pack("<H", len(fw_payload) // CHUNK))) total = 0 for part in chunks(fw_payload, CHUNK): if not send_retries(device, part): return error_cb("Error while sending data, firmware is corrupted") total += len(part) progress_cb(total / len(fw_payload)) # Reboot log_cb("Rebooting...") # enable insecure mode on first boot in order to restore keymap/macros if enable_insecure: send_retries(device, pad_for_vibl(b"VC\x04")) send_retries(device, pad_for_vibl(b"VC\x03")) complete_cb("Done!")
def get_uid(self): try: super().open() except OSError: return b"" self.send(pad_for_vibl(b"VC\x01")) data = self.recv(8, timeout_ms=500) super().close() return data