2024-01-12 14:42:01 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2023-11-01 12:40:50 +00:00
|
|
|
#include "flash_otp.h"
|
2023-06-30 10:12:55 +00:00
|
|
|
#include "model.h"
|
2024-01-12 14:42:01 +00:00
|
|
|
#include "unit_variant.h"
|
|
|
|
#include TREZOR_BOARD
|
2023-04-14 15:18:03 +00:00
|
|
|
|
|
|
|
static uint8_t unit_variant_color = 0;
|
|
|
|
static bool unit_variant_btconly = false;
|
|
|
|
static bool unit_variant_ok = false;
|
|
|
|
|
2024-01-12 14:42:01 +00:00
|
|
|
static int16_t unit_variant_build_year = -1;
|
|
|
|
|
2023-04-14 15:18:03 +00:00
|
|
|
static void unit_variant_0x01(const uint8_t *data) {
|
|
|
|
unit_variant_color = data[1];
|
|
|
|
unit_variant_btconly = data[2] == 1;
|
|
|
|
unit_variant_ok = true;
|
|
|
|
}
|
|
|
|
|
2024-01-12 14:42:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-04-14 15:18:03 +00:00
|
|
|
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);
|
|
|
|
|
2024-01-12 14:42:01 +00:00
|
|
|
unit_variant_build_year = unit_variant_get_build_year();
|
|
|
|
|
2023-04-14 15:18:03 +00:00
|
|
|
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; }
|
|
|
|
|
|
|
|
bool unit_variant_get_btconly(void) { return unit_variant_btconly; }
|
|
|
|
|
|
|
|
bool unit_variant_present(void) { return unit_variant_ok; }
|
2024-01-12 14:42:01 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|