diff --git a/core/embed/extmod/modtrezorio/modtrezorio-sdcard.h b/core/embed/extmod/modtrezorio/modtrezorio-sdcard.h index 9dc9833303..1cdbdbbcd8 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-sdcard.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-sdcard.h @@ -113,6 +113,16 @@ STATIC mp_obj_t mod_trezorio_sdcard_write(mp_obj_t block_num, mp_obj_t buf) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_sdcard_write_obj, mod_trezorio_sdcard_write); +/// def get_mid() -> int: +/// """ +/// Returns Manufacturer ID from the CID register data. +/// """ +STATIC mp_obj_t mod_trezorio_sdcard_get_mid() { + return mp_obj_new_int_from_ull(sdcard_get_mid()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_sdcard_get_mid_obj, + mod_trezorio_sdcard_get_mid); + STATIC const mp_rom_map_elem_t mod_trezorio_sdcard_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcard)}, @@ -125,9 +135,12 @@ STATIC const mp_rom_map_elem_t mod_trezorio_sdcard_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_capacity), MP_ROM_PTR(&mod_trezorio_sdcard_capacity_obj)}, {MP_ROM_QSTR(MP_QSTR_BLOCK_SIZE), MP_ROM_INT(SDCARD_BLOCK_SIZE)}, - {MP_ROM_QSTR(MP_QSTR_BACKUP_BLOCK_START), MP_ROM_INT(SDCARD_BACKUP_BLOCK_START)}, + {MP_ROM_QSTR(MP_QSTR_BACKUP_BLOCK_START), + MP_ROM_INT(SDCARD_BACKUP_BLOCK_START)}, {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_sdcard_read_obj)}, {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_sdcard_write_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_mid), + MP_ROM_PTR(&mod_trezorio_sdcard_get_mid_obj)}, }; STATIC MP_DEFINE_CONST_DICT(mod_trezorio_sdcard_globals, mod_trezorio_sdcard_globals_table); diff --git a/core/embed/trezorhal/sdcard.h b/core/embed/trezorhal/sdcard.h index d21a9066ed..186e9efc50 100644 --- a/core/embed/trezorhal/sdcard.h +++ b/core/embed/trezorhal/sdcard.h @@ -63,5 +63,6 @@ secbool __wur sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_blocks); secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t num_blocks); +uint64_t __wur sdcard_get_mid(void); #endif diff --git a/core/embed/trezorhal/stm32f4/sdcard.c b/core/embed/trezorhal/stm32f4/sdcard.c index 728c548064..9f8a58f5f7 100644 --- a/core/embed/trezorhal/stm32f4/sdcard.c +++ b/core/embed/trezorhal/stm32f4/sdcard.c @@ -402,3 +402,12 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, return sectrue * (err == HAL_OK); } + +uint64_t __wur sdcard_get_mid(void) { + if (sd_handle.Instance == NULL) { + return 0; + } + HAL_SD_CardCIDTypeDef res = {0}; + HAL_SD_GetCardCID(&sd_handle, &res); + return (uint64_t)res.ManufacturerID; +} diff --git a/core/embed/trezorhal/unix/sdcard.c b/core/embed/trezorhal/unix/sdcard.c index c06e7a3b49..9929bd5ecd 100644 --- a/core/embed/trezorhal/unix/sdcard.c +++ b/core/embed/trezorhal/unix/sdcard.c @@ -130,3 +130,8 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, num_blocks * SDCARD_BLOCK_SIZE); return sectrue; } + +uint64_t __wur sdcard_get_mid(void) { + // TODO mock + return 0; +} diff --git a/core/mocks/generated/trezorio/sdcard.pyi b/core/mocks/generated/trezorio/sdcard.pyi index 7fe2dbf8f5..b0e63b01c2 100644 --- a/core/mocks/generated/trezorio/sdcard.pyi +++ b/core/mocks/generated/trezorio/sdcard.pyi @@ -49,3 +49,10 @@ def write(block_num: int, buf: bytes) -> None: Number of bytes written is length of buf rounded down to multiply of SDCARD_BLOCK_SIZE. """ + + +# extmod/modtrezorio/modtrezorio-sdcard.h +def get_mid() -> int: + """ + Returns Manufacturer ID from the CID register data. + """ diff --git a/core/src/apps/common/sdcard.py b/core/src/apps/common/sdcard.py index dfd7fb54ee..40539544f3 100644 --- a/core/src/apps/common/sdcard.py +++ b/core/src/apps/common/sdcard.py @@ -1,5 +1,5 @@ from trezor import io, wire -from trezor.sdcard import SD_CARD_HOT_SWAPPABLE +from trezor.sdcard import SD_CARD_HOT_SWAPPABLE, with_sdcard from trezor.ui.layouts import confirm_action, show_error_and_raise @@ -108,6 +108,7 @@ async def ensure_sdcard( if not ensure_filesystem: return + fatfs = io.fatfs # local_cache_attribute while True: try: @@ -157,3 +158,20 @@ async def request_sd_salt() -> bytearray | None: # In either case, there is no good way to recover. If the user clicks Retry, # we will try again. await confirm_retry_sd() + + +@with_sdcard +def is_trz_card() -> bool: + iosd = io.sdcard # local_cache_attribute + if not iosd.is_present(): + return False + return iosd.get_mid() == 39 and iosd.capacity() == 122_945_536 + + +@with_sdcard +async def show_sd_card_info() -> None: + from trezor.ui.layouts import show_success + + mid = io.sdcard.get_mid() + cap = io.sdcard.capacity() + await show_success("TDL", f"Manuf ID: {mid}\nCapacity: {cap} [B]") diff --git a/core/src/apps/management/backup_types.py b/core/src/apps/management/backup_types.py index ba901a2ea9..599a7039ce 100644 --- a/core/src/apps/management/backup_types.py +++ b/core/src/apps/management/backup_types.py @@ -22,7 +22,9 @@ def is_slip39_word_count(word_count: int) -> bool: raise RuntimeError -def is_slip39_backup_type(backup_type: BackupType) -> bool: +def is_slip39_backup_type(backup_type: BackupType | None) -> bool: + if backup_type is None: + return False return backup_type in (BackupType.Slip39_Basic, BackupType.Slip39_Advanced) diff --git a/core/src/apps/management/recovery_device/homescreen.py b/core/src/apps/management/recovery_device/homescreen.py index b0203d6e11..4cd0ff467b 100644 --- a/core/src/apps/management/recovery_device/homescreen.py +++ b/core/src/apps/management/recovery_device/homescreen.py @@ -152,7 +152,6 @@ async def _finish_recovery_dry_run( async def _finish_recovery(secret: bytes, backup_type: BackupType) -> Success: - from trezor.enums import BackupType from trezor.ui.layouts import show_success if backup_type is None: @@ -204,6 +203,7 @@ async def _recover_mnemonic_or_share( # ask for the number of words word_count = await layout.request_word_count(dry_run) await _request_share_first_screen(word_count) + assert word_count is not None words = await layout.request_mnemonic(word_count, backup_type) return words, word_count, BackupMedium.Words else: @@ -212,10 +212,11 @@ async def _recover_mnemonic_or_share( try: mnemonic, _ = await sdcard_recover_seed() # TODO backup type needed? - if mnemonic == None: + if mnemonic is None: # TODO warn and repeat pass - return mnemonic, len(mnemonic.split()), BackupMedium.SDCard + else: + return mnemonic, len(mnemonic.split()), BackupMedium.SDCard except wire.ActionCancelled: # there might have been a backup # TODO show guidance: Pick different card/choose words diff --git a/core/src/apps/management/reset_device/__init__.py b/core/src/apps/management/reset_device/__init__.py index f97a493cf5..744002aa50 100644 --- a/core/src/apps/management/reset_device/__init__.py +++ b/core/src/apps/management/reset_device/__init__.py @@ -148,7 +148,8 @@ async def _backup_mnemonic_or_share( await sdcard_backup_seed(mnemonic, backup_type) return except ActionCancelled: - # there might have been a backup + # 1) Not a Trezor card. + # 2) Backup present on the card. # TODO show guidance: Pick different card/choose words pass except Exception: diff --git a/core/src/apps/management/sd_backup.py b/core/src/apps/management/sd_backup.py index 5b9af746e8..aa6e7bfe59 100644 --- a/core/src/apps/management/sd_backup.py +++ b/core/src/apps/management/sd_backup.py @@ -23,12 +23,19 @@ async def sdcard_backup_seed(mnemonic_secret: bytes, backup_type: BackupType) -> from storage.sd_seed_backup import is_backup_present, store_seed_on_sdcard from trezor.ui.layouts import confirm_action, show_success - from apps.common.sdcard import ensure_sdcard + from apps.common.sdcard import ensure_sdcard, is_trz_card await ensure_sdcard(ensure_filesystem=False) + if not is_trz_card(): + await confirm_action( + "confirm_not_trezor_card", + "Not Trezor card", + action="This is not Trezor Card! Still continue?", + verb="Continue", + ) if is_backup_present(): await confirm_action( - "warning_sdcard_backup_exists", + "confirm_sdcard_backup_exists", "Backup present", action="There is already a Trezor backup on this card!", description="Replace the backup?", diff --git a/core/src/trezor/sdcard.py b/core/src/trezor/sdcard.py index be6c2047e3..6ae31653c4 100644 --- a/core/src/trezor/sdcard.py +++ b/core/src/trezor/sdcard.py @@ -28,10 +28,6 @@ if TYPE_CHECKING: SD_CARD_HOT_SWAPPABLE = False -def is_trz_card() -> bool: - return True - - class FilesystemWrapper: _INSTANCE: "FilesystemWrapper" | None = None diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 9ab36b0b30..ca6fb64b4b 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -583,7 +583,7 @@ async def choose_backup_medium( from storage.sd_seed_backup import BackupMedium if share_index is None: - action = f"Recovery seed" + action = "Recovery seed" description = "You can backup your wallet using either SD card or word list." elif group_index is None: action = f"Recovery share #{share_index + 1}"