2019-10-25 15:43:55 +00:00
|
|
|
import storage.sd_salt
|
2019-11-08 11:42:30 +00:00
|
|
|
from storage.sd_salt import SD_CARD_HOT_SWAPPABLE
|
2021-05-13 10:33:52 +00:00
|
|
|
from trezor import io, sdcard, ui, wire
|
2021-03-10 11:56:44 +00:00
|
|
|
from trezor.ui.layouts import confirm_action, show_error_and_raise
|
2019-08-13 15:50:06 +00:00
|
|
|
|
|
|
|
|
2020-02-17 14:51:39 +00:00
|
|
|
class SdCardUnavailable(wire.ProcessError):
|
2019-08-13 15:50:06 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2021-03-10 11:56:44 +00:00
|
|
|
async def _confirm_retry_wrong_card(ctx: wire.GenericContext) -> None:
|
2019-09-24 13:32:39 +00:00
|
|
|
if SD_CARD_HOT_SWAPPABLE:
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_wrong_sd",
|
|
|
|
"SD card protection",
|
|
|
|
action="Wrong SD card.",
|
|
|
|
description="Please insert the correct SD card for this device.",
|
|
|
|
verb="Retry",
|
|
|
|
verb_cancel="Abort",
|
|
|
|
icon=ui.ICON_WRONG,
|
|
|
|
larger_vspace=True,
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("Wrong SD card."),
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2019-09-24 13:32:39 +00:00
|
|
|
else:
|
2021-03-10 11:56:44 +00:00
|
|
|
await show_error_and_raise(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_wrong_sd",
|
|
|
|
header="SD card protection",
|
|
|
|
subheader="Wrong SD card.",
|
|
|
|
content="Please unplug the\ndevice and insert the correct SD card.",
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("Wrong SD card."),
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2019-08-13 15:50:06 +00:00
|
|
|
|
|
|
|
|
2021-03-10 11:56:44 +00:00
|
|
|
async def _confirm_retry_insert_card(ctx: wire.GenericContext) -> None:
|
2019-09-24 13:32:39 +00:00
|
|
|
if SD_CARD_HOT_SWAPPABLE:
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_no_sd",
|
|
|
|
"SD card protection",
|
|
|
|
action="SD card required.",
|
|
|
|
description="Please insert your SD card.",
|
|
|
|
verb="Retry",
|
|
|
|
verb_cancel="Abort",
|
|
|
|
icon=ui.ICON_WRONG,
|
|
|
|
larger_vspace=True,
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("SD card required."),
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2019-09-24 13:32:39 +00:00
|
|
|
else:
|
2021-03-10 11:56:44 +00:00
|
|
|
await show_error_and_raise(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_no_sd",
|
|
|
|
header="SD card protection",
|
|
|
|
subheader="SD card required.",
|
|
|
|
content="Please unplug the\ndevice and insert your SD card.",
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("SD card required."),
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2019-09-24 13:32:39 +00:00
|
|
|
|
|
|
|
|
2021-03-10 11:56:44 +00:00
|
|
|
async def _confirm_format_card(ctx: wire.GenericContext) -> None:
|
2020-02-17 14:51:39 +00:00
|
|
|
# Format card? yes/no
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_format_sd",
|
|
|
|
"SD card error",
|
|
|
|
action="Unknown filesystem.",
|
|
|
|
description="Use a different card or format the SD card to the FAT32 filesystem.",
|
|
|
|
icon=ui.ICON_WRONG,
|
|
|
|
icon_color=ui.RED,
|
|
|
|
verb="Format",
|
|
|
|
verb_cancel="Cancel",
|
|
|
|
larger_vspace=True,
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("SD card not formatted."),
|
|
|
|
)
|
2020-02-17 14:51:39 +00:00
|
|
|
|
|
|
|
# Confirm formatting
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"confirm_format_sd",
|
|
|
|
"Format SD card",
|
|
|
|
action="All data on the SD card will be lost.",
|
|
|
|
description="Do you really want to format the SD card?",
|
|
|
|
reverse=True,
|
|
|
|
verb="Format SD card",
|
|
|
|
icon=ui.ICON_WIPE,
|
|
|
|
icon_color=ui.RED,
|
|
|
|
hold=True,
|
|
|
|
larger_vspace=True,
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=SdCardUnavailable("SD card not formatted."),
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2020-02-17 14:51:39 +00:00
|
|
|
|
|
|
|
|
2021-03-10 11:56:44 +00:00
|
|
|
async def confirm_retry_sd(
|
|
|
|
ctx: wire.GenericContext,
|
|
|
|
exc: wire.ProcessError = SdCardUnavailable("Error accessing SD card."),
|
|
|
|
) -> None:
|
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
ctx,
|
|
|
|
"warning_sd_retry",
|
|
|
|
"SD card problem",
|
|
|
|
action=None,
|
|
|
|
description="There was a problem accessing the SD card.",
|
|
|
|
icon=ui.ICON_WRONG,
|
|
|
|
icon_color=ui.RED,
|
|
|
|
verb="Retry",
|
|
|
|
verb_cancel="Abort",
|
2021-03-10 11:56:44 +00:00
|
|
|
exc=exc,
|
2021-02-10 17:36:08 +00:00
|
|
|
)
|
2019-10-02 15:27:11 +00:00
|
|
|
|
|
|
|
|
2020-02-21 14:53:53 +00:00
|
|
|
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.
|
|
|
|
"""
|
2020-02-17 14:51:39 +00:00
|
|
|
while not sdcard.is_present():
|
2021-03-10 11:56:44 +00:00
|
|
|
await _confirm_retry_insert_card(ctx)
|
2020-02-17 14:51:39 +00:00
|
|
|
|
2020-02-21 14:53:53 +00:00
|
|
|
if not ensure_filesystem:
|
|
|
|
return
|
|
|
|
|
2020-02-17 14:51:39 +00:00
|
|
|
while True:
|
|
|
|
try:
|
2020-03-20 10:18:46 +00:00
|
|
|
try:
|
|
|
|
with sdcard.filesystem(mounted=False):
|
2021-05-13 10:33:52 +00:00
|
|
|
io.fatfs.mount()
|
|
|
|
except io.fatfs.NoFilesystem:
|
2020-03-20 10:18:46 +00:00
|
|
|
# card not formatted. proceed out of the except clause
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
# no error when mounting
|
2020-02-17 14:51:39 +00:00
|
|
|
return
|
|
|
|
|
2021-03-10 11:56:44 +00:00
|
|
|
await _confirm_format_card(ctx)
|
2020-02-17 14:51:39 +00:00
|
|
|
|
2020-03-20 10:18:46 +00:00
|
|
|
# Proceed to formatting. Failure is caught by the outside OSError handler
|
2020-02-26 18:25:22 +00:00
|
|
|
with sdcard.filesystem(mounted=False):
|
2021-05-13 10:33:52 +00:00
|
|
|
io.fatfs.mkfs()
|
|
|
|
io.fatfs.mount()
|
|
|
|
io.fatfs.setlabel("TREZOR")
|
2020-02-26 18:25:22 +00:00
|
|
|
|
2020-03-20 10:18:46 +00:00
|
|
|
# format and mount succeeded
|
|
|
|
return
|
|
|
|
|
|
|
|
except OSError:
|
|
|
|
# formatting failed, or generic I/O error (SD card power-on failed)
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_retry_sd(ctx)
|
2019-10-18 11:53:00 +00:00
|
|
|
|
|
|
|
|
2019-08-13 15:50:06 +00:00
|
|
|
async def request_sd_salt(
|
2019-11-20 15:02:47 +00:00
|
|
|
ctx: wire.GenericContext = wire.DUMMY_CONTEXT,
|
2021-03-18 09:48:50 +00:00
|
|
|
) -> bytearray | None:
|
2019-11-11 15:16:42 +00:00
|
|
|
if not storage.sd_salt.is_enabled():
|
|
|
|
return None
|
|
|
|
|
2019-10-09 17:35:26 +00:00
|
|
|
while True:
|
2020-02-21 14:53:53 +00:00
|
|
|
await ensure_sdcard(ctx, ensure_filesystem=False)
|
2019-10-09 17:35:26 +00:00
|
|
|
try:
|
2019-10-25 15:43:55 +00:00
|
|
|
return storage.sd_salt.load_sd_salt()
|
2021-05-13 10:33:52 +00:00
|
|
|
except (storage.sd_salt.WrongSdCard, io.fatfs.NoFilesystem):
|
2021-03-10 11:56:44 +00:00
|
|
|
await _confirm_retry_wrong_card(ctx)
|
2019-08-13 15:50:06 +00:00
|
|
|
except OSError:
|
2020-03-05 11:58:09 +00:00
|
|
|
# Generic problem with loading the SD salt (hardware problem, or we could
|
|
|
|
# not read the file, or there is a staged salt which cannot be committed).
|
2019-11-08 11:42:30 +00:00
|
|
|
# In either case, there is no good way to recover. If the user clicks Retry,
|
|
|
|
# we will try again.
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_retry_sd(ctx)
|