2024-09-26 13:14:12 +00:00
|
|
|
from trezor import TR, io, wire
|
2021-03-10 11:56:44 +00:00
|
|
|
from trezor.ui.layouts import confirm_action, show_error_and_raise
|
2024-01-12 14:42:01 +00:00
|
|
|
from trezor.utils import sd_hotswap_enabled
|
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
|
|
|
|
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
async def _confirm_retry_wrong_card() -> None:
|
2024-01-12 14:42:01 +00:00
|
|
|
if sd_hotswap_enabled():
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
"warning_wrong_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__title,
|
|
|
|
TR.sd_card__wrong_sd_card,
|
|
|
|
TR.sd_card__insert_correct_card,
|
|
|
|
verb=TR.buttons__retry,
|
|
|
|
verb_cancel=TR.buttons__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
|
|
|
"warning_wrong_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__unplug_and_insert_correct,
|
|
|
|
TR.sd_card__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
|
|
|
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
async def _confirm_retry_insert_card() -> None:
|
2024-01-12 14:42:01 +00:00
|
|
|
if sd_hotswap_enabled():
|
2021-03-10 11:56:44 +00:00
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
"warning_no_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__title,
|
|
|
|
TR.sd_card__card_required,
|
|
|
|
TR.sd_card__please_insert,
|
|
|
|
verb=TR.buttons__retry,
|
|
|
|
verb_cancel=TR.buttons__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
|
|
|
"warning_no_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__please_unplug_and_insert,
|
|
|
|
TR.sd_card__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
|
|
|
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
async def _confirm_format_card() -> 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
|
|
|
"warning_format_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__error,
|
|
|
|
TR.sd_card__unknown_filesystem,
|
|
|
|
TR.sd_card__use_different_card,
|
|
|
|
verb=TR.buttons__format,
|
|
|
|
verb_cancel=TR.buttons__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
|
|
|
"confirm_format_sd",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__format_card,
|
|
|
|
TR.sd_card__all_data_will_be_lost,
|
|
|
|
TR.sd_card__wanna_format,
|
2021-02-10 17:36:08 +00:00
|
|
|
reverse=True,
|
2023-08-11 15:57:32 +00:00
|
|
|
verb=TR.sd_card__format_card,
|
2021-02-10 17:36:08 +00:00
|
|
|
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(
|
|
|
|
exc: wire.ProcessError = SdCardUnavailable("Error accessing SD card."),
|
|
|
|
) -> None:
|
|
|
|
await confirm_action(
|
2021-02-10 17:36:08 +00:00
|
|
|
"warning_sd_retry",
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__title_problem,
|
2022-09-19 09:17:36 +00:00
|
|
|
None,
|
2023-08-11 15:57:32 +00:00
|
|
|
TR.sd_card__problem_accessing,
|
|
|
|
verb=TR.buttons__retry,
|
|
|
|
verb_cancel=TR.buttons__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
|
|
|
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
async def ensure_sdcard(ensure_filesystem: bool = True) -> None:
|
2020-02-21 14:53:53 +00:00
|
|
|
"""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
|
2024-07-04 07:32:59 +00:00
|
|
|
from trezor.ui.layouts.progress import progress
|
2022-09-19 09:17:36 +00:00
|
|
|
|
2020-02-17 14:51:39 +00:00
|
|
|
while not sdcard.is_present():
|
2023-06-26 11:42:10 +00:00
|
|
|
await _confirm_retry_insert_card()
|
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
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
await _confirm_format_card()
|
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):
|
2024-07-04 07:32:59 +00:00
|
|
|
progress_obj = progress()
|
|
|
|
progress_obj.start()
|
|
|
|
fatfs.mkfs(progress_obj.report)
|
2022-09-19 09:17:36 +00:00
|
|
|
fatfs.mount()
|
|
|
|
fatfs.setlabel("TREZOR")
|
2024-07-04 07:32:59 +00:00
|
|
|
progress_obj.stop()
|
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)
|
2023-06-26 11:42:10 +00:00
|
|
|
await confirm_retry_sd()
|
2019-10-18 11:53:00 +00:00
|
|
|
|
|
|
|
|
2023-06-26 11:42:10 +00:00
|
|
|
async def request_sd_salt() -> 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:
|
2023-06-26 11:42:10 +00:00
|
|
|
await ensure_sdcard(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):
|
2023-06-26 11:42:10 +00:00
|
|
|
await _confirm_retry_wrong_card()
|
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.
|
2023-06-26 11:42:10 +00:00
|
|
|
await confirm_retry_sd()
|