diff --git a/python/.changelog.d/1738.added b/python/.changelog.d/1738.added new file mode 100644 index 00000000000..2e40897a986 --- /dev/null +++ b/python/.changelog.d/1738.added @@ -0,0 +1 @@ +trezorctl: new command `device reboot-to-bootloader` reboots T1 to bootloader diff --git a/python/src/trezorlib/cli/device.py b/python/src/trezorlib/cli/device.py index 39bd18e1ef8..bb6e37598f2 100644 --- a/python/src/trezorlib/cli/device.py +++ b/python/src/trezorlib/cli/device.py @@ -258,3 +258,17 @@ def sd_protect(client, operation): if client.features.model == "1": raise click.BadUsage("Trezor One does not support SD card protection.") return device.sd_protect(client, operation) + + +@cli.command() +@click.pass_obj +def reboot_to_bootloader(obj): + """Reboot device into bootloader mode.""" + # avoid using @with_client because it closes the session afterwards, + # which triggers double prompt on device + with obj.client_context() as client: + if client.features.model != "1": + click.echo( + f"Warning: Rebooting into bootloader not supported on Trezor {client.features.model}" + ) + return device.reboot_to_bootloader(client) diff --git a/python/src/trezorlib/cli/trezorctl.py b/python/src/trezorlib/cli/trezorctl.py index e1554855202..1d501c42df5 100755 --- a/python/src/trezorlib/cli/trezorctl.py +++ b/python/src/trezorlib/cli/trezorctl.py @@ -190,6 +190,8 @@ def print_result(res, is_json, **kwargs): click.echo("%s.%s: %s" % (k, kk, vv)) else: click.echo("%s: %s" % (k, v)) + elif isinstance(res, messages.Success): + click.echo(res.message) elif isinstance(res, protobuf.MessageType): click.echo(protobuf.format_message(res)) elif res is not None: diff --git a/python/src/trezorlib/device.py b/python/src/trezorlib/device.py index 2179cd19be4..d6187e4614d 100644 --- a/python/src/trezorlib/device.py +++ b/python/src/trezorlib/device.py @@ -209,3 +209,9 @@ def backup(client): @expect(messages.Success, field="message") def cancel_authorization(client): return client.call(messages.CancelAuthorization()) + + +@session +@expect(messages.Success) +def reboot_to_bootloader(client): + return client.call(messages.RebootToBootloader())