1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-04 05:28:17 +00:00
trezor-firmware/core/src/apps/common/sdcard.py

165 lines
4.9 KiB
Python
Raw Normal View History

from storage.sd_salt import SD_CARD_HOT_SWAPPABLE
from trezor import io, wire
from trezor.ui.layouts import confirm_action, show_error_and_raise
2019-08-13 15:50:06 +00:00
class SdCardUnavailable(wire.ProcessError):
2019-08-13 15:50:06 +00:00
pass
async def _confirm_retry_wrong_card(ctx: wire.GenericContext) -> None:
if SD_CARD_HOT_SWAPPABLE:
await confirm_action(
ctx,
"warning_wrong_sd",
"SD card protection",
"Wrong SD card.",
"Please insert the correct SD card for this device.",
verb="Retry",
verb_cancel="Abort",
exc=SdCardUnavailable("Wrong SD card."),
)
else:
await show_error_and_raise(
ctx,
"warning_wrong_sd",
"Please unplug the device and insert the correct SD card.",
"Wrong SD card.",
exc=SdCardUnavailable("Wrong SD card."),
)
2019-08-13 15:50:06 +00:00
async def _confirm_retry_insert_card(ctx: wire.GenericContext) -> None:
if SD_CARD_HOT_SWAPPABLE:
await confirm_action(
ctx,
"warning_no_sd",
"SD card protection",
"SD card required.",
"Please insert your SD card.",
verb="Retry",
verb_cancel="Abort",
exc=SdCardUnavailable("SD card required."),
)
else:
await show_error_and_raise(
ctx,
"warning_no_sd",
"Please unplug the device and insert your SD card.",
"SD card required.",
exc=SdCardUnavailable("SD card required."),
)
async def _confirm_format_card(ctx: wire.GenericContext) -> None:
# Format card? yes/no
await confirm_action(
ctx,
"warning_format_sd",
"SD card error",
"Unknown filesystem.",
"Use a different card or format the SD card to the FAT32 filesystem.",
verb="Format",
verb_cancel="Cancel",
exc=SdCardUnavailable("SD card not formatted."),
)
# Confirm formatting
await confirm_action(
ctx,
"confirm_format_sd",
"Format SD card",
"All data on the SD card will be lost.",
"Do you really want to format the SD card?",
reverse=True,
verb="Format SD card",
hold=True,
exc=SdCardUnavailable("SD card not formatted."),
)
async def confirm_retry_sd(
ctx: wire.GenericContext,
exc: wire.ProcessError = SdCardUnavailable("Error accessing SD card."),
) -> None:
await confirm_action(
ctx,
"warning_sd_retry",
"SD card problem",
None,
"There was a problem accessing the SD card.",
verb="Retry",
verb_cancel="Abort",
exc=exc,
)
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.
"""
from trezor import sdcard
while not sdcard.is_present():
await _confirm_retry_insert_card(ctx)
if not ensure_filesystem:
return
fatfs = io.fatfs # local_cache_attribute
while True:
try:
try:
with sdcard.filesystem(mounted=False):
fatfs.mount()
except fatfs.NoFilesystem:
# card not formatted. proceed out of the except clause
pass
else:
# no error when mounting
return
await _confirm_format_card(ctx)
# Proceed to formatting. Failure is caught by the outside OSError handler
2020-02-26 18:25:22 +00:00
with sdcard.filesystem(mounted=False):
fatfs.mkfs()
fatfs.mount()
fatfs.setlabel("TREZOR")
2020-02-26 18:25:22 +00:00
# format and mount succeeded
return
except OSError:
# formatting failed, or generic I/O error (SD card power-on failed)
await confirm_retry_sd(ctx)
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,
) -> bytearray | None:
import storage.sd_salt as storage_sd_salt
if not storage_sd_salt.is_enabled():
return None
while True:
await ensure_sdcard(ctx, ensure_filesystem=False)
try:
return storage_sd_salt.load_sd_salt()
except (storage_sd_salt.WrongSdCard, io.fatfs.NoFilesystem):
await _confirm_retry_wrong_card(ctx)
2019-08-13 15:50:06 +00:00
except OSError:
# 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).
# In either case, there is no good way to recover. If the user clicks Retry,
# we will try again.
await confirm_retry_sd(ctx)