core/sdcard: add ensure_filesystem option (fixes #868)

It is possible to call `ensure_sdcard` in a way that requires only SD
card be inserted, but not necessarily formatted.

This is useful for SD-protect and possibly other use-cases where the SD
card is read-only, and "not formatted" is identical to "not containing
the right files".
pull/873/head
matejcik 4 years ago committed by matejcik
parent e9c275c24f
commit d7b9582386

@ -70,11 +70,25 @@ async def sd_problem_dialog(ctx: wire.GenericContext) -> bool:
return await confirm(ctx, text, confirm="Retry", cancel="Abort")
async def ensure_sdcard(ctx: wire.GenericContext) -> None:
async def ensure_sdcard(
ctx: wire.GenericContext, ensure_filesystem: bool = True
) -> None:
"""Ensure a SD card is ready for use.
This function runs the UI flow needed to ask the user to insert a SD card if there
isn't one.
If `ensure_filesystem` is True (the default), it also tries to mount the SD card
filesystem, and allows the user to format the card if a filesystem cannot be
mounted.
"""
while not sdcard.is_present():
if not await insert_card_dialog(ctx):
raise SdCardUnavailable("SD card required.")
if not ensure_filesystem:
return
while True:
try:
with sdcard.get_filesystem(mounted=False) as fs:
@ -105,7 +119,7 @@ async def request_sd_salt(
return None
while True:
await ensure_sdcard(ctx)
await ensure_sdcard(ctx, ensure_filesystem=False)
try:
return storage.sd_salt.load_sd_salt()
except storage.sd_salt.WrongSdCard:
@ -117,4 +131,4 @@ async def request_sd_salt(
# In either case, there is no good way to recover. If the user clicks Retry,
# we will try again.
if not await sd_problem_dialog(ctx):
raise
raise SdCardUnavailable("Error accessing SD card.")

@ -43,3 +43,70 @@ def test_sd_no_format(client):
device.sd_protect(client, Op.ENABLE)
assert e.value.failure.code == messages.FailureType.ProcessError
@pytest.mark.sd_card
@pytest.mark.setup_client(pin="1234")
def test_sd_protect_unlock(client):
def input_flow_enable_sd_protect():
yield # do you really want to enable SD protection
assert "SD card protection" in client.debug.wait_layout().text
client.debug.press_yes()
yield # enter current PIN
assert "PinDialog" == client.debug.wait_layout().text
client.debug.input("1234")
yield # you have successfully enabled SD protection
assert "Success" in client.debug.wait_layout().text
client.debug.press_yes()
with client:
client.set_input_flow(input_flow_enable_sd_protect)
device.sd_protect(client, Op.ENABLE)
def input_flow_change_pin():
yield # do you really want to change PIN?
assert "Change PIN" in client.debug.wait_layout().text
client.debug.press_yes()
yield # enter current PIN
assert "PinDialog" == client.debug.wait_layout().text
client.debug.input("1234")
yield # enter new PIN
assert "PinDialog" == client.debug.wait_layout().text
client.debug.input("1234")
yield # enter new PIN again
assert "PinDialog" == client.debug.wait_layout().text
client.debug.input("1234")
yield # Pin change successful
assert "Success" in client.debug.wait_layout().text
client.debug.press_yes()
with client:
client.set_input_flow(input_flow_change_pin)
device.change_pin(client)
client.debug.erase_sd_card(format=False)
def input_flow_change_pin_format():
yield # do you really want to change PIN?
assert "Change PIN" in client.debug.wait_layout().text
client.debug.press_yes()
yield # SD card problem
assert "SD card problem" in client.debug.wait_layout().text
client.debug.press_yes() # retry
yield # still SD card problem
assert "SD card problem" in client.debug.wait_layout().text
client.debug.press_no() # do not retry
with client, pytest.raises(TrezorFailure) as e:
client.set_input_flow(input_flow_change_pin_format)
device.change_pin(client)
assert e.value.failure.code == messages.FailureType.ProcessError

@ -388,6 +388,7 @@
"test_reset_backup.py::test_skip_backup_msg[2-backup_flow_slip39_advanced]": "df213fe327a775563fd8c442ed1ed2dfe5053d56d50307059292d5a5fe091b4c",
"test_sdcard.py::test_sd_format": "e0da54c8a26386bff4eb310e9c7ebaa56a02fed3870f976d1dd3b230750a28fe",
"test_sdcard.py::test_sd_no_format": "f47e897caee95cf98c1b4506732825f853c4b8afcdc2713e38e3b4055973c9ac",
"test_sdcard.py::test_sd_protect_unlock": "0b6cb625b59256552505575bce75fb0895b935d574f2a07ac4a5246d608252af",
"test_u2f_counter.py::test_u2f_counter": "7d96a4d262b9d8a2c1158ac1e5f0f7b2c3ed5f2ba9d6235a014320313f9488fe",
"test_zerosig.py-test_one_zero_signature": "401aeaf7b2f565e2064a3c1a57a8ee3afe1e9bf251fba0874390685e7e0f178f",
"test_zerosig.py-test_two_zero_signature": "7a01a057fb5dd3e6e38e7986875c5d07f0700bd80b519660e0b42973a9afd664"

Loading…
Cancel
Save