From 5845c665af324063bdd937c1e0b133a859f39bb1 Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 1 Oct 2024 16:15:01 +0200 Subject: [PATCH] refactor(core): refactor unit properties detection [no changelog] --- core/SConscript.bootloader | 1 - core/SConscript.bootloader_emu | 2 +- core/SConscript.firmware | 1 - core/SConscript.kernel | 1 - core/SConscript.unix | 2 +- core/embed/bootloader/main.c | 6 +- core/embed/bootloader/messages.c | 14 +- .../extmod/modtrezorutils/modtrezorutils.c | 16 +- core/embed/kernel/main.c | 4 +- core/embed/lib/unit_variant.c | 100 ---------- core/embed/lib/unit_variant.h | 20 -- .../trezorhal/stm32f4/syscall_dispatch.c | 23 +-- .../embed/trezorhal/stm32f4/syscall_numbers.h | 6 +- core/embed/trezorhal/stm32f4/syscall_stubs.c | 23 +-- .../trezorhal/stm32f4/syscall_verifiers.c | 15 ++ .../trezorhal/stm32f4/syscall_verifiers.h | 5 + .../embed/trezorhal/stm32f4/unit_properties.c | 177 ++++++++++++++++++ .../embed/trezorhal/stm32u5/unit_properties.c | 1 + core/embed/trezorhal/unit_properties.h | 70 +++++++ core/embed/trezorhal/unix/unit_properties.c | 84 +++++++++ core/embed/unix/main.c | 3 + core/site_scons/models/stm32f4_common.py | 5 +- core/site_scons/models/stm32u5_common.py | 5 +- 23 files changed, 396 insertions(+), 188 deletions(-) delete mode 100644 core/embed/lib/unit_variant.c delete mode 100644 core/embed/lib/unit_variant.h create mode 100644 core/embed/trezorhal/stm32f4/unit_properties.c create mode 120000 core/embed/trezorhal/stm32u5/unit_properties.c create mode 100644 core/embed/trezorhal/unit_properties.h create mode 100644 core/embed/trezorhal/unix/unit_properties.c diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 0c05e7838d..70cca73006 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -81,7 +81,6 @@ SOURCE_MOD += [ 'embed/lib/mini_printf.c', 'embed/lib/rsod.c', 'embed/lib/terminal.c', - 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index d8ace1f240..789f27b428 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -86,7 +86,6 @@ SOURCE_MOD += [ 'embed/lib/mini_printf.c', 'embed/lib/rsod.c', 'embed/lib/terminal.c', - 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', @@ -131,6 +130,7 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/unix/system.c', 'embed/trezorhal/unix/systick.c', 'embed/trezorhal/unix/systimer.c', + 'embed/trezorhal/unix/unit_properties.c', 'embed/trezorhal/unix/usb.c', ] diff --git a/core/SConscript.firmware b/core/SConscript.firmware index fe9843a1eb..27a2d0dd4e 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -212,7 +212,6 @@ SOURCE_MOD += [ 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', - 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', diff --git a/core/SConscript.kernel b/core/SConscript.kernel index 8e0c6756bf..80f3b0d7d3 100644 --- a/core/SConscript.kernel +++ b/core/SConscript.kernel @@ -199,7 +199,6 @@ SOURCE_MOD += [ 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', - 'embed/lib/unit_variant.c', 'embed/extmod/modtrezorcrypto/rand.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', diff --git a/core/SConscript.unix b/core/SConscript.unix index bc791f69d2..5f6840e3ca 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -222,7 +222,6 @@ SOURCE_MOD += [ 'embed/lib/rsod.c', 'embed/lib/terminal.c', 'embed/lib/translations.c', - 'embed/lib/unit_variant.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', @@ -405,6 +404,7 @@ SOURCE_UNIX = [ 'embed/trezorhal/unix/systick.c', 'embed/trezorhal/unix/systimer.c', 'embed/trezorhal/unix/time_estimate.c', + 'embed/trezorhal/unix/unit_properties.c', 'embed/trezorhal/unix/usb.c', 'embed/unix/main_main.c', 'embed/unix/main.c', diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 3409fdf630..7e50044a3b 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -75,7 +75,7 @@ #include "messages.h" #include "monoctr.h" #include "rust_ui.h" -#include "unit_variant.h" +#include "unit_properties.h" #include "version_check.h" #ifdef TREZOR_EMULATOR @@ -375,7 +375,7 @@ int bootloader_main(void) { dma2d_init(); #endif - unit_variant_init(); + unit_properties_init(); #ifdef USE_TOUCH secbool touch_initialized = secfalse; @@ -384,7 +384,7 @@ int bootloader_main(void) { // on T3T1, tester needs to run without touch, so making an exception // until unit variant is written in OTP const secbool manufacturing_mode = - unit_variant_present() ? secfalse : sectrue; + unit_properties()->locked ? secfalse : sectrue; allow_touchless_mode = manufacturing_mode; #endif diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index 3cf0abee78..8b011af498 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -31,7 +31,7 @@ #include "image.h" #include "secbool.h" #include "secret.h" -#include "unit_variant.h" +#include "unit_properties.h" #include "usb.h" #include "version.h" @@ -315,10 +315,14 @@ static void send_msg_features(uint8_t iface_num, } else { MSG_SEND_ASSIGN_VALUE(firmware_present, false); } - if (unit_variant_present()) { - MSG_SEND_ASSIGN_VALUE(unit_color, unit_variant_get_color()); - MSG_SEND_ASSIGN_VALUE(unit_packaging, unit_variant_get_packaging()); - MSG_SEND_ASSIGN_VALUE(unit_btconly, unit_variant_get_btconly()); + if (unit_properties()->color_is_valid) { + MSG_SEND_ASSIGN_VALUE(unit_color, unit_properties()->color); + } + if (unit_properties()->packaging_is_valid) { + MSG_SEND_ASSIGN_VALUE(unit_packaging, unit_properties()->packaging); + } + if (unit_properties()->btconly_is_valid) { + MSG_SEND_ASSIGN_VALUE(unit_btconly, unit_properties()->btconly); } #if USE_OPTIGA diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index 21444bc5a7..ca04f00b41 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -33,7 +33,7 @@ #include "bootutils.h" #include "error_handling.h" #include "fwutils.h" -#include "unit_variant.h" +#include "unit_properties.h" #include "usb.h" #include TREZOR_BOARD #include "model.h" @@ -195,10 +195,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_firmware_vendor_obj, /// Returns the color of the unit. /// """ STATIC mp_obj_t mod_trezorutils_unit_color(void) { - if (!unit_variant_present()) { + if (!unit_properties()->color_is_valid) { return mp_const_none; } - return mp_obj_new_int(unit_variant_get_color()); + return mp_obj_new_int(unit_properties()->color); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_color_obj, mod_trezorutils_unit_color); @@ -208,10 +208,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_color_obj, /// Returns True if the unit is BTConly. /// """ STATIC mp_obj_t mod_trezorutils_unit_btconly(void) { - if (!unit_variant_present()) { + if (!unit_properties()->btconly_is_valid) { return mp_const_none; } - return unit_variant_get_btconly() ? mp_const_true : mp_const_false; + return unit_properties()->btconly ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_btconly_obj, mod_trezorutils_unit_btconly); @@ -221,10 +221,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_btconly_obj, /// Returns the packaging version of the unit. /// """ STATIC mp_obj_t mod_trezorutils_unit_packaging(void) { - if (!unit_variant_present()) { + if (!unit_properties()->packaging_is_valid) { return mp_const_none; } - return mp_obj_new_int(unit_variant_get_packaging()); + return mp_obj_new_int(unit_properties()->packaging); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_packaging_obj, mod_trezorutils_unit_packaging); @@ -234,7 +234,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_unit_packaging_obj, /// 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; + return unit_properties()->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); diff --git a/core/embed/kernel/main.c b/core/embed/kernel/main.c index f6194a705a..fac2f12eaf 100644 --- a/core/embed/kernel/main.c +++ b/core/embed/kernel/main.c @@ -46,7 +46,7 @@ #include "systick.h" #include "tamper.h" #include "touch.h" -#include "unit_variant.h" +#include "unit_properties.h" #ifdef USE_OPTIGA #if !PYOPT @@ -103,7 +103,7 @@ void drivers_init() { parse_boardloader_capabilities(); - unit_variant_init(); + unit_properties_init(); #ifdef STM32U5 secure_aes_init(); diff --git a/core/embed/lib/unit_variant.c b/core/embed/lib/unit_variant.c deleted file mode 100644 index 6fffb7049d..0000000000 --- a/core/embed/lib/unit_variant.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "flash_otp.h" -#include "model.h" -#include "mpu.h" -#include "unit_variant.h" -#include TREZOR_BOARD - -#ifdef KERNEL_MODE - -static uint8_t unit_variant_color = 0; -static uint8_t unit_variant_packaging = 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_packaging = data[3]; - 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: - unit_variant_0x01(data); - break; - default: - break; - } - } -} - -uint8_t unit_variant_get_color(void) { return unit_variant_color; } - -uint8_t unit_variant_get_packaging(void) { return unit_variant_packaging; } - -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 -} - -#endif // KERNEL_MODE diff --git a/core/embed/lib/unit_variant.h b/core/embed/lib/unit_variant.h deleted file mode 100644 index fea6d77b0c..0000000000 --- a/core/embed/lib/unit_variant.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _UNIT_VARIANT_H -#define _UNIT_VARIANT_H - -#include -#include - -#ifdef KERNEL_MODE - -void unit_variant_init(void); - -#endif // KERNEL_MODE - -bool unit_variant_present(void); -uint8_t unit_variant_get_color(void); -uint8_t unit_variant_get_packaging(void); -bool unit_variant_get_btconly(void); - -bool unit_variant_is_sd_hotswap_enabled(void); - -#endif //_UNIT_VARIANT_H diff --git a/core/embed/trezorhal/stm32f4/syscall_dispatch.c b/core/embed/trezorhal/stm32f4/syscall_dispatch.c index 09cb204bc7..f0bb5f92f7 100644 --- a/core/embed/trezorhal/stm32f4/syscall_dispatch.c +++ b/core/embed/trezorhal/stm32f4/syscall_dispatch.c @@ -40,7 +40,7 @@ #include "systick.h" #include "touch.h" #include "translations.h" -#include "unit_variant.h" +#include "unit_properties.h" #include "usb.h" #include "usb_hid.h" #include "usb_vcp.h" @@ -379,24 +379,9 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args, } break; #endif - case SYSCALL_UNIT_VARIANT_PRESENT: { - args[0] = unit_variant_present(); - } break; - - case SYSCALL_UNIT_VARIANT_GET_COLOR: { - args[0] = unit_variant_get_color(); - } break; - - case SYSCALL_UNIT_VARIANT_GET_PACKAGING: { - args[0] = unit_variant_get_packaging(); - } break; - - case SYSCALL_UNIT_VARIANT_GET_BTCONLY: { - args[0] = unit_variant_get_btconly(); - } break; - - case SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED: { - args[0] = unit_variant_is_sd_hotswap_enabled(); + case SYSCALL_UNIT_PROPERTIES_GET: { + unit_properties_t *props = (unit_properties_t *)args[0]; + unit_properties_get__verified(props); } break; case SYSCALL_SECRET_BOOTLOADER_LOCKED: { diff --git a/core/embed/trezorhal/stm32f4/syscall_numbers.h b/core/embed/trezorhal/stm32f4/syscall_numbers.h index 17da29be1a..3d29f1f070 100644 --- a/core/embed/trezorhal/stm32f4/syscall_numbers.h +++ b/core/embed/trezorhal/stm32f4/syscall_numbers.h @@ -84,11 +84,7 @@ typedef enum { SYSCALL_SDCARD_READ_BLOCKS, SYSCALL_SDCARD_WRITE_BLOCKS, - SYSCALL_UNIT_VARIANT_PRESENT, - SYSCALL_UNIT_VARIANT_GET_COLOR, - SYSCALL_UNIT_VARIANT_GET_PACKAGING, - SYSCALL_UNIT_VARIANT_GET_BTCONLY, - SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED, + SYSCALL_UNIT_PROPERTIES_GET, SYSCALL_SECRET_BOOTLOADER_LOCKED, diff --git a/core/embed/trezorhal/stm32f4/syscall_stubs.c b/core/embed/trezorhal/stm32f4/syscall_stubs.c index d71ef34daf..952808d0a7 100644 --- a/core/embed/trezorhal/stm32f4/syscall_stubs.c +++ b/core/embed/trezorhal/stm32f4/syscall_stubs.c @@ -334,32 +334,21 @@ secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, } // ============================================================================= -// unit_variant.h +// unit_properties.h // ============================================================================= -bool unit_variant_present(void) { - return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_PRESENT); -} -uint8_t unit_variant_get_color(void) { - return (uint8_t)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_COLOR); -} +#include "unit_properties.h" -uint8_t unit_variant_get_packaging(void) { - return (uint8_t)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_PACKAGING); -} - -bool unit_variant_get_btconly(void) { - return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_GET_BTCONLY); -} - -bool unit_variant_is_sd_hotswap_enabled(void) { - return (bool)syscall_invoke0(SYSCALL_UNIT_VARIANT_IS_SD_HOTSWAP_ENABLED); +void unit_properties_get(unit_properties_t *props) { + syscall_invoke1((uint32_t)props, SYSCALL_UNIT_PROPERTIES_GET); } // ============================================================================= // secret.h // ============================================================================= +#include "secret.h" + secbool secret_bootloader_locked(void) { return (secbool)syscall_invoke0(SYSCALL_SECRET_BOOTLOADER_LOCKED); } diff --git a/core/embed/trezorhal/stm32f4/syscall_verifiers.c b/core/embed/trezorhal/stm32f4/syscall_verifiers.c index caa578ceae..6aaf7da095 100644 --- a/core/embed/trezorhal/stm32f4/syscall_verifiers.c +++ b/core/embed/trezorhal/stm32f4/syscall_verifiers.c @@ -389,6 +389,21 @@ access_violation: // --------------------------------------------------------------------- +void unit_properties_get__verified(unit_properties_t *props) { + if (!probe_write_access(props, sizeof(*props))) { + goto access_violation; + } + + unit_properties_get(props); + + return; + +access_violation: + apptask_access_violation(); +} + +// --------------------------------------------------------------------- + optiga_sign_result __wur optiga_sign__verified( uint8_t index, const uint8_t *digest, size_t digest_size, uint8_t *signature, size_t max_sig_size, size_t *sig_size) { diff --git a/core/embed/trezorhal/stm32f4/syscall_verifiers.h b/core/embed/trezorhal/stm32f4/syscall_verifiers.h index 5f3bb18d62..11e2846e00 100644 --- a/core/embed/trezorhal/stm32f4/syscall_verifiers.h +++ b/core/embed/trezorhal/stm32f4/syscall_verifiers.h @@ -99,6 +99,11 @@ secbool __wur sdcard_write_blocks__verified(const uint32_t *src, uint32_t block_num, uint32_t num_blocks); +// --------------------------------------------------------------------- +#include "unit_properties.h" + +void unit_properties_get__verified(unit_properties_t *props); + // --------------------------------------------------------------------- #include "optiga.h" diff --git a/core/embed/trezorhal/stm32f4/unit_properties.c b/core/embed/trezorhal/stm32f4/unit_properties.c new file mode 100644 index 0000000000..276e5994f0 --- /dev/null +++ b/core/embed/trezorhal/stm32f4/unit_properties.c @@ -0,0 +1,177 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include TREZOR_BOARD + +#include + +#include "flash_otp.h" +#include "model.h" +#include "unit_properties.h" + +#ifdef KERNEL_MODE + +// Unit properties driver structure +typedef struct { + // Set to true if the unit properties are valid + bool initialized; + // Cached unit properties data + unit_properties_t cache; + +} unit_properties_driver_t; + +// Unit properties driver instance +static unit_properties_driver_t g_unit_properties_driver = { + .initialized = false, +}; + +#ifdef TREZOR_MODEL_T + +// Parse two digit number from the string. +// +// Returns -1 if the string is not a valid two-digit number. +static inline int parse_two_digits(const char* str) { + if (str[0] < '0' || str[0] > '9' || str[1] < '0' || str[1] > '9') { + return -1; + } + return (str[0] - '0') * 10 + (str[1] - '0'); +} + +// Reads the production date from the OTP block. +// +// Returns `false` in case of and flash read error. +static bool get_production_date(int* year) { + *year = -1; + + uint8_t otp_data[FLASH_OTP_BLOCK_SIZE]; + + // Batch block contains a string with the build date. + // Expecting format {MODEL_IDENTIFIER}-YYMMDD. + // https://docs.trezor.io/trezor-firmware/core/misc/memory.html?highlight=otp#otp + + if (sectrue != flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, otp_data, + FLASH_OTP_BLOCK_SIZE)) { + return false; + } + + if (otp_data[0] != 0xFF) { + char* str = (char*)otp_data; + + // Last 7 characters are the date "-YYMMDD" + int i = strnlen(str, FLASH_OTP_BLOCK_SIZE) - 7; + + if (i >= 0 && str[i] == '-') { + *year = parse_two_digits(&str[i + 1]); + } + } + + return true; +} + +#endif // TREZOR_MODEL_T + +// Reads and parses the unit properties from the OTP block. +// +// Returns `false` in case of and flash read error. +static bool detect_properties(unit_properties_t* props) { + uint8_t otp_data[FLASH_OTP_BLOCK_SIZE]; + + props->locked = flash_otp_is_locked(FLASH_OTP_BLOCK_DEVICE_VARIANT); + + if (sectrue != flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT, 0, otp_data, + FLASH_OTP_BLOCK_SIZE)) { + return false; + } + + switch (otp_data[0]) { + case 0xFF: + // OTP block were not written yet, keep the defaults + break; + + case 0x01: + // The field were gradually added to the OTP block over time. + // Unused trailing bytes were always set to 0x00. + props->color = otp_data[1]; + props->color_is_valid = true; + props->btconly = otp_data[2] == 1; + props->btconly_is_valid = true; + props->packaging = otp_data[3]; + props->packaging_is_valid = true; + break; + + default: + // Unknown variant, be conservative and keep the defaults + break; + } + +#ifdef USE_SD_CARD + props->sd_hotswap_enabled = true; +#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. + int production_year; + get_production_date(&production_year); + if (production_year <= 18) { + props->sd_hotswap_enabled = false; + } +#endif +#endif + + return true; +} + +bool unit_properties_init(void) { + unit_properties_driver_t* drv = &g_unit_properties_driver; + + if (drv->initialized) { + return true; + } + + memset(drv, 0, sizeof(unit_properties_driver_t)); + + if (!detect_properties(&drv->cache)) { + return false; + } + + drv->initialized = true; + + return true; +} + +void unit_properties_get(unit_properties_t* props) { + unit_properties_driver_t* drv = &g_unit_properties_driver; + + ensure(sectrue * drv->initialized, "Unit properties not initialized"); + + *props = drv->cache; +} + +#endif // KERNEL_MODE + +const unit_properties_t* unit_properties(void) { + static bool cache_initialized = false; + static unit_properties_t cache = {0}; + + if (!cache_initialized) { + unit_properties_get(&cache); + cache_initialized = true; + } + + return &cache; +} diff --git a/core/embed/trezorhal/stm32u5/unit_properties.c b/core/embed/trezorhal/stm32u5/unit_properties.c new file mode 120000 index 0000000000..d1874a0bc4 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/unit_properties.c @@ -0,0 +1 @@ +../stm32f4/unit_properties.c \ No newline at end of file diff --git a/core/embed/trezorhal/unit_properties.h b/core/embed/trezorhal/unit_properties.h new file mode 100644 index 0000000000..5011c6bbfb --- /dev/null +++ b/core/embed/trezorhal/unit_properties.h @@ -0,0 +1,70 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TREZORHAL_UNIT_PROPERTIES_H +#define TREZORHAL_UNIT_PROPERTIES_H + +#include +#include + +#ifdef KERNEL_MODE + +// Initializes module a detects the unit properties +// +// Returns `true` if the properties are successfully detected +bool unit_properties_init(void); + +#endif // KERNEL_MODE + +typedef struct { + // Set to true if the unit properties are locked and cannot be changed + // (the device is in the production mode) + bool locked; + + // Unit color. The value is opaque to the firmware and is + // used only by Trezor Suite. + uint8_t color; + // Set if `color` field contains a valid value + bool color_is_valid; + + // Unit packaging. The value is opaque for the firmware and is + // used only by Trezor Suite. + uint8_t packaging; + // Set if `packaging` field contains a valid value + bool packaging_is_valid; + + // Set to true if the unit is BTC only + bool btconly; + // Set if `btconly` field contains a valid value + bool btconly_is_valid; + + // Set to true if the SD card hotswap is enabled + bool sd_hotswap_enabled; + +} unit_properties_t; + +// Gets a copy of unit properties structure +// +// Properties are detected just once during the initialization. +void unit_properties_get(unit_properties_t* props); + +// Gets a pointer to the static unit properties structure +const unit_properties_t* unit_properties(void); + +#endif // TREZORHAL_UNIT_PROPERTIES_H diff --git a/core/embed/trezorhal/unix/unit_properties.c b/core/embed/trezorhal/unix/unit_properties.c new file mode 100644 index 0000000000..76de8598cf --- /dev/null +++ b/core/embed/trezorhal/unix/unit_properties.c @@ -0,0 +1,84 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include TREZOR_BOARD + +#include + +#include "flash_otp.h" +#include "model.h" +#include "unit_properties.h" + +// Unit properties driver structure +typedef struct { + // Set to true if the unit properties are valid + bool initialized; + // Cached unit properties data + unit_properties_t cache; + +} unit_properties_driver_t; + +// Unit properties driver instance +static unit_properties_driver_t g_unit_properties_driver = { + .initialized = false, +}; + +bool unit_properties_init(void) { + unit_properties_driver_t* drv = &g_unit_properties_driver; + + if (drv->initialized) { + return true; + } + + memset(drv, 0, sizeof(unit_properties_driver_t)); + +#ifdef USE_SD_CARD + drv->cache.sd_hotswap_enabled = true; +#ifdef TREZOR_MODEL_T + drv->cache.sd_hotswap_enabled = false; +#endif +#endif + + // Properties detection is not fully implemented for emulator. + // Default values are used. + + drv->initialized = true; + + return true; +} + +void unit_properties_get(unit_properties_t* props) { + unit_properties_driver_t* drv = &g_unit_properties_driver; + + ensure(sectrue * drv->initialized, "Unit properties not initialized"); + + *props = drv->cache; +} + +const unit_properties_t* unit_properties(void) { + static bool cache_initialized = false; + static unit_properties_t cache = {0}; + + if (!cache_initialized) { + unit_properties_get(&cache); + cache_initialized = true; + } + + return &cache; +} diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index 0666325b91..aa8b285b0c 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -49,6 +49,7 @@ #include "system.h" #include "systimer.h" #include "touch.h" +#include "unit_properties.h" #include "py/builtin.h" #include "py/compile.h" @@ -501,6 +502,8 @@ MP_NOINLINE int main_(int argc, char **argv) { flash_init(); flash_otp_init(); + unit_properties_init(); + #if MICROPY_ENABLE_GC char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py index 2996479e80..9f44b6a0f7 100644 --- a/core/site_scons/models/stm32f4_common.py +++ b/core/site_scons/models/stm32f4_common.py @@ -53,6 +53,8 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/monoctr.c", "embed/trezorhal/stm32f4/mpu.c", "embed/trezorhal/stm32f4/platform.c", + "embed/trezorhal/stm32f4/random_delays.c", + "embed/trezorhal/stm32f4/rng.c", "embed/trezorhal/stm32f4/secret.c", "embed/trezorhal/stm32f4/syscall.c", "embed/trezorhal/stm32f4/syscall_dispatch.c", @@ -64,8 +66,7 @@ def stm32f4_common_files(env, defines, sources, paths): "embed/trezorhal/stm32f4/systick.c", "embed/trezorhal/stm32f4/systimer.c", "embed/trezorhal/stm32f4/time_estimate.c", - "embed/trezorhal/stm32f4/random_delays.c", - "embed/trezorhal/stm32f4/rng.c", + "embed/trezorhal/stm32f4/unit_properties.c", "embed/trezorhal/stm32f4/vectortable.S", ] diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py index f6d343033d..46183ba1e1 100644 --- a/core/site_scons/models/stm32u5_common.py +++ b/core/site_scons/models/stm32u5_common.py @@ -63,6 +63,8 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/monoctr.c", "embed/trezorhal/stm32u5/mpu.c", "embed/trezorhal/stm32u5/platform.c", + "embed/trezorhal/stm32u5/random_delays.c", + "embed/trezorhal/stm32u5/rng.c", "embed/trezorhal/stm32u5/secret.c", "embed/trezorhal/stm32u5/secure_aes.c", "embed/trezorhal/stm32u5/syscall.c", @@ -74,11 +76,10 @@ def stm32u5_common_files(env, defines, sources, paths): "embed/trezorhal/stm32u5/systask.c", "embed/trezorhal/stm32u5/systick.c", "embed/trezorhal/stm32u5/systimer.c", - "embed/trezorhal/stm32u5/random_delays.c", - "embed/trezorhal/stm32u5/rng.c", "embed/trezorhal/stm32u5/tamper.c", "embed/trezorhal/stm32u5/time_estimate.c", "embed/trezorhal/stm32u5/trustzone.c", + "embed/trezorhal/stm32u5/unit_properties.c", "embed/trezorhal/stm32u5/vectortable.S", ]