diff --git a/core/.changelog.d/3940.added b/core/.changelog.d/3940.added new file mode 100644 index 000000000..3d19564b2 --- /dev/null +++ b/core/.changelog.d/3940.added @@ -0,0 +1 @@ +[T2T1] Allow SD card hotswap based on production date diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index b0ce35e48..2cde2041a 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -253,6 +253,16 @@ STATIC mp_obj_t mod_trezorutils_unit_btconly(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_btconly_obj, mod_trezorutils_unit_btconly); +/// def sd_hotswap_enabled() -> bool: +/// """ +/// Returns True if SD card hot swapping is enabled +/// """ +STATIC mp_obj_t mod_trezorutils_sd_hotswap_enabled(void) { + return unit_variant_is_sd_hotswap_enabled() ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_sd_hotswap_enabled_obj, + mod_trezorutils_sd_hotswap_enabled); + /// def reboot_to_bootloader( /// boot_command : int = 0, /// boot_args : bytes | None = None, @@ -415,6 +425,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = { MP_ROM_PTR(&mod_trezorutils_unit_color_obj)}, {MP_ROM_QSTR(MP_QSTR_unit_btconly), MP_ROM_PTR(&mod_trezorutils_unit_btconly_obj)}, + {MP_ROM_QSTR(MP_QSTR_sd_hotswap_enabled), + MP_ROM_PTR(&mod_trezorutils_sd_hotswap_enabled_obj)}, // various built-in constants {MP_ROM_QSTR(MP_QSTR_SCM_REVISION), MP_ROM_PTR(&mod_trezorutils_revision_obj)}, diff --git a/core/embed/lib/unit_variant.c b/core/embed/lib/unit_variant.c index 4cc3b567a..2a2bb4d76 100644 --- a/core/embed/lib/unit_variant.c +++ b/core/embed/lib/unit_variant.c @@ -1,23 +1,61 @@ -#include "unit_variant.h" +#include + #include "flash_otp.h" #include "model.h" +#include "unit_variant.h" +#include TREZOR_BOARD static uint8_t unit_variant_color = 0; static bool unit_variant_btconly = false; static bool unit_variant_ok = false; +static int16_t unit_variant_build_year = -1; + static void unit_variant_0x01(const uint8_t *data) { unit_variant_color = data[1]; unit_variant_btconly = data[2] == 1; unit_variant_ok = true; } +static int16_t unit_variant_get_build_year(void) { + uint8_t data[FLASH_OTP_BLOCK_SIZE] = {0}; + + secbool result = + flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, FLASH_OTP_BLOCK_SIZE); + + if (sectrue != result || data[0] == 0xFF) { + return -1; + } + + /** + * Expecting format {MODEL_IDENTIFIER}-YYMMDD + * + * See also + * https://docs.trezor.io/trezor-firmware/core/misc/memory.html?highlight=otp#otp + */ + + size_t len = strnlen((char *)data, FLASH_OTP_BLOCK_SIZE); + + for (int i = 0; i < len; i++) { + if (data[i] == '-') { + if ((len - (i + 1)) != 6) { + return -1; + } + return ((int16_t)data[i + 1] - (int16_t)'0') * 10 + + ((int16_t)data[i + 2] - (int16_t)'0'); + } + } + return -1; +} + void unit_variant_init(void) { uint8_t data[FLASH_OTP_BLOCK_SIZE]; secbool result = flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT, 0, data, FLASH_OTP_BLOCK_SIZE); + unit_variant_build_year = unit_variant_get_build_year(); + if (sectrue == result) { switch (data[0]) { case 0x01: @@ -34,3 +72,20 @@ uint8_t unit_variant_get_color(void) { return unit_variant_color; } bool unit_variant_get_btconly(void) { return unit_variant_btconly; } bool unit_variant_present(void) { return unit_variant_ok; } + +bool unit_variant_is_sd_hotswap_enabled(void) { +#ifndef USE_SD_CARD + return false; +#else +#ifdef TREZOR_MODEL_T + // early produced TTs have a HW bug that prevents hotswapping of the SD card, + // lets check the build data and decide based on that + if (unit_variant_build_year <= 18) { + return false; + } + return true; +#else + return true; +#endif +#endif +} diff --git a/core/embed/lib/unit_variant.h b/core/embed/lib/unit_variant.h index 110af2660..72915a8a3 100644 --- a/core/embed/lib/unit_variant.h +++ b/core/embed/lib/unit_variant.h @@ -9,4 +9,6 @@ bool unit_variant_present(void); uint8_t unit_variant_get_color(void); bool unit_variant_get_btconly(void); +bool unit_variant_is_sd_hotswap_enabled(void); + #endif //_UNIT_VARIANT_H diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index 2f7a16728..331173a74 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -619,7 +619,7 @@ int main(void) { draw_welcome_screen(); char dom[32]; - // format: TREZOR2-YYMMDD + // format: {MODEL_IDENTIFIER}-YYMMDD if (sectrue == flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, (uint8_t *)dom, 32) && sectrue == startswith(dom, MODEL_IDENTIFIER) && dom[31] == 0) { display_qrcode(DISPLAY_RESX / 2, DISPLAY_RESY / 2, dom, 4); diff --git a/core/mocks/generated/trezorutils.pyi b/core/mocks/generated/trezorutils.pyi index 4ba9cdbf2..94dc4d6de 100644 --- a/core/mocks/generated/trezorutils.pyi +++ b/core/mocks/generated/trezorutils.pyi @@ -74,6 +74,13 @@ def unit_btconly() -> bool | None: """ +# extmod/modtrezorutils/modtrezorutils.c +def sd_hotswap_enabled() -> bool: + """ + Returns True if SD card hot swapping is enabled + """ + + # extmod/modtrezorutils/modtrezorutils.c def reboot_to_bootloader( boot_command : int = 0, diff --git a/core/src/apps/common/sdcard.py b/core/src/apps/common/sdcard.py index c6446e05c..e5d0ba96b 100644 --- a/core/src/apps/common/sdcard.py +++ b/core/src/apps/common/sdcard.py @@ -1,6 +1,6 @@ -from storage.sd_salt import SD_CARD_HOT_SWAPPABLE from trezor import TR, io, wire from trezor.ui.layouts import confirm_action, show_error_and_raise +from trezor.utils import sd_hotswap_enabled class SdCardUnavailable(wire.ProcessError): @@ -8,7 +8,7 @@ class SdCardUnavailable(wire.ProcessError): async def _confirm_retry_wrong_card() -> None: - if SD_CARD_HOT_SWAPPABLE: + if sd_hotswap_enabled(): await confirm_action( "warning_wrong_sd", TR.sd_card__title, @@ -28,7 +28,7 @@ async def _confirm_retry_wrong_card() -> None: async def _confirm_retry_insert_card() -> None: - if SD_CARD_HOT_SWAPPABLE: + if sd_hotswap_enabled(): await confirm_action( "warning_no_sd", TR.sd_card__title, diff --git a/core/src/storage/sd_salt.py b/core/src/storage/sd_salt.py index 2bc8b9b35..90714436e 100644 --- a/core/src/storage/sd_salt.py +++ b/core/src/storage/sd_salt.py @@ -13,7 +13,6 @@ if TYPE_CHECKING: if utils.USE_SD_CARD: fatfs = io.fatfs # global_import_cache -SD_CARD_HOT_SWAPPABLE = False SD_SALT_LEN_BYTES = const(32) _SD_SALT_AUTH_TAG_LEN_BYTES = const(16) diff --git a/core/src/trezor/utils.py b/core/src/trezor/utils.py index e42d944f2..15eec59f7 100644 --- a/core/src/trezor/utils.py +++ b/core/src/trezor/utils.py @@ -20,6 +20,7 @@ from trezorutils import ( # noqa: F401 halt, memcpy, reboot_to_bootloader, + sd_hotswap_enabled, unit_btconly, unit_color, ) diff --git a/docs/core/misc/memory.md b/docs/core/misc/memory.md index 1f1c595d9..55cec1490 100644 --- a/docs/core/misc/memory.md +++ b/docs/core/misc/memory.md @@ -33,7 +33,7 @@ | block | range | size | function |----------|-------------------------|------|-------------------------------- -| block 0 | 0x1FFF7800 - 0x1FFF781F | 32 B | device batch (week of manufacture) +| block 0 | 0x1FFF7800 - 0x1FFF781F | 32 B | device batch: {MODEL_IDENTIFIER}-YYMMDD | block 1 | 0x1FFF7820 - 0x1FFF783F | 32 B | bootloader downgrade protection | block 2 | 0x1FFF7840 - 0x1FFF785F | 32 B | vendor keys lock | block 3 | 0x1FFF7860 - 0x1FFF787F | 32 B | entropy/randomness