2019-11-08 11:42:30 +00:00
|
|
|
from storage.sd_salt import SD_CARD_HOT_SWAPPABLE
|
2022-10-20 12:28:29 +00:00
|
|
|
from trezor import io, 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",
|
2022-09-19 09:17:36 +00:00
|
|
|
"Wrong SD card.",
|
|
|
|
"Please insert the correct SD card for this device.",
|
2021-02-10 17:36:08 +00:00
|
|
|
verb="Retry",
|
|
|
|
verb_cancel="Abort",
|
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",
|
2023-01-20 13:57:33 +00:00
|
|
|
"Please unplug the device and insert the correct SD card.",
|
2022-09-19 09:17:36 +00:00
|
|
|
"Wrong 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",
|
2022-09-19 09:17:36 +00:00
|
|
|
"SD card required.",
|
|
|
|
"Please insert your SD card.",
|
2021-02-10 17:36:08 +00:00
|
|
|
verb="Retry",
|
|
|
|
verb_cancel="Abort",
|
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",
|
2023-01-20 13:57:33 +00:00
|
|
|
"Please unplug the device and insert your SD card.",
|
2022-09-19 09:17:36 +00:00
|
|
|
"SD card required.",
|
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",
|
2022-09-19 09:17:36 +00:00
|
|
|
"Unknown filesystem.",
|
|
|
|
"Use a different card or format the SD card to the FAT32 filesystem.",
|
2021-02-10 17:36:08 +00:00
|
|
|
verb="Format",
|
|
|
|
verb_cancel="Cancel",
|
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",
|
2022-09-19 09:17:36 +00:00
|
|
|
"All data on the SD card will be lost.",
|
|
|
|
"Do you really want to format the SD card?",
|
2021-02-10 17:36:08 +00:00
|
|
|
reverse=True,
|
|
|
|
verb="Format SD card",
|
|
|
|
hold=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",
|
2022-09-19 09:17:36 +00:00
|
|
|
None,
|
|
|
|
"There was a problem accessing the SD card.",
|
2021-02-10 17:36:08 +00:00
|
|
|
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.
|
|
|
|
"""
|
2022-09-19 09:17:36 +00:00
|
|
|
from trezor import sdcard
|
|
|
|
|
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
|
2022-09-19 09:17:36 +00:00
|
|
|
fatfs = io.fatfs # local_cache_attribute
|
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):
|
2022-09-19 09:17:36 +00:00
|
|
|
fatfs.mount()
|
|
|
|
except 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):
|
2022-09-19 09:17:36 +00:00
|
|
|
fatfs.mkfs()
|
|
|
|
fatfs.mount()
|
|
|
|
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:
|
2022-09-19 09:17:36 +00:00
|
|
|
import storage.sd_salt as storage_sd_salt
|
|
|
|
|
|
|
|
if not storage_sd_salt.is_enabled():
|
2019-11-11 15:16:42 +00:00
|
|
|
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:
|
2022-09-19 09:17:36 +00:00
|
|
|
return storage_sd_salt.load_sd_salt()
|
|
|
|
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)
|