1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-06 10:16:07 +00:00

feat(core/prodtest): support writing device ID into OTP memory

This commit is contained in:
tychovrahe 2025-03-05 10:27:36 +01:00
parent a18abd8e54
commit d0684a5e28
4 changed files with 73 additions and 9 deletions

View File

@ -26,3 +26,4 @@
#define FLASH_OTP_BLOCK_RANDOMNESS 3
#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4
#define FLASH_OTP_BLOCK_FIRMWARE_VERSION 5
#define FLASH_OTP_BLOCK_DEVICE_ID 6

View File

@ -0,0 +1 @@
Added device ID write/read commands.

View File

@ -469,6 +469,7 @@ If the OTP memory has not been written yet, it returns error code `no-data`.
Example:
```
otp-batch-read
# Reading device OTP memory...
# Bytes read: <hexadecimal string>
ERROR no-data "OTP block is empty."
@ -493,6 +494,39 @@ otp-batch-write T2B1-231231 --dry-run
# Locking OTP block...
```
### otp-device-id-read
Retrieves the device ID string from the device's OTP memory. The device ID string is unique for each device.
If the OTP memory has not been written yet, it returns error code `no-data`.
Example:
```
otp-device-id-read
# Reading device OTP memory...
# Bytes read: <hexadecimal string>
ERROR no-data "OTP block is empty."
```
### otp-device-id-write
Writes the device ID string to the device's OTP memory. The device ID string is unique for each device.
The batch string can be up to 31 characters in length.
In non-production firmware, you must include `--execute` as the last parameter to write the data to the OTP memory. Conversely, in production firmware, you can use `--dry-run` as the last parameter to simulate the command without actually writing to the OTP memory.
Example:
```
otp-device-id-write 123456ABCD --dry-run
#
# !!! It's a dry run, OTP will be left unchanged.
# !!! Use '--execute' switch to write to OTP memory.
#
# Writing device batch info into OTP memory...
# Bytes written: 3132333435364142434400000000000000000000000000000000000000000000
# Locking OTP block...
```
### otp-variant-write
Writes up to 31 decimal values, each representing device variant options, to device's OTP memory. Each value must range from 0 to 255.

View File

@ -23,7 +23,7 @@
#include <rtl/cli.h>
#include <util/flash_otp.h>
static void prodtest_otp_batch_read(cli_t* cli) {
static void prodtest_otp_read(cli_t* cli, uint8_t block_num) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
return;
@ -33,8 +33,7 @@ static void prodtest_otp_batch_read(cli_t* cli) {
cli_trace(cli, "Reading device OTP memory...");
if (sectrue !=
flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, block, sizeof(block))) {
if (sectrue != flash_otp_read(block_num, 0, block, sizeof(block))) {
cli_error(cli, CLI_ERROR, "Failed to read OTP memory.");
return;
}
@ -64,7 +63,7 @@ static void prodtest_otp_batch_read(cli_t* cli) {
}
}
static void prodtest_otp_batch_write(cli_t* cli) {
static void prodtest_otp_write(cli_t* cli, uint8_t block_num) {
const char* data = cli_arg(cli, "text");
if (strlen(data) == 0 || strlen(data) > FLASH_OTP_BLOCK_SIZE - 1) {
@ -111,18 +110,17 @@ static void prodtest_otp_batch_write(cli_t* cli) {
return;
}
if (sectrue == flash_otp_is_locked(FLASH_OTP_BLOCK_BATCH)) {
if (sectrue == flash_otp_is_locked(block_num)) {
cli_error(cli, CLI_ERROR_LOCKED,
"OTP block is locked and cannot be written again.");
return;
}
cli_trace(cli, "Writing device batch info into OTP memory...");
cli_trace(cli, "Writing info into OTP memory...");
cli_trace(cli, "Bytes written: %s", block_hex);
if (!dry_run) {
if (sectrue !=
flash_otp_write(FLASH_OTP_BLOCK_BATCH, 0, block, sizeof(block))) {
if (sectrue != flash_otp_write(block_num, 0, block, sizeof(block))) {
cli_error(cli, CLI_ERROR, "Failed to write OTP block.");
return;
}
@ -131,7 +129,7 @@ static void prodtest_otp_batch_write(cli_t* cli) {
cli_trace(cli, "Locking OTP block...");
if (!dry_run) {
if (sectrue != flash_otp_lock(FLASH_OTP_BLOCK_BATCH)) {
if (sectrue != flash_otp_lock(block_num)) {
cli_error(cli, CLI_ERROR, "Failed to lock the OTP block.");
return;
}
@ -141,6 +139,22 @@ static void prodtest_otp_batch_write(cli_t* cli) {
cli_ok(cli, "");
}
static void prodtest_otp_batch_read(cli_t* cli) {
prodtest_otp_read(cli, FLASH_OTP_BLOCK_BATCH);
}
static void prodtest_otp_batch_write(cli_t* cli) {
prodtest_otp_write(cli, FLASH_OTP_BLOCK_BATCH);
}
static void prodtest_otp_device_id_read(cli_t* cli) {
prodtest_otp_read(cli, FLASH_OTP_BLOCK_DEVICE_ID);
}
static void prodtest_otp_device_id_write(cli_t* cli) {
prodtest_otp_write(cli, FLASH_OTP_BLOCK_DEVICE_ID);
}
// clang-format off
PRODTEST_CLI_CMD(
@ -156,3 +170,17 @@ PRODTEST_CLI_CMD(
.info = "Write the device batch info into OTP memory",
.args = "<text> [--execute | --dry-run]"
);
PRODTEST_CLI_CMD(
.name = "otp-device-id-read",
.func = prodtest_otp_device_id_read,
.info = "Read the device ID from OTP memory",
.args = ""
);
PRODTEST_CLI_CMD(
.name = "otp-device-id-write",
.func = prodtest_otp_device_id_write,
.info = "Write the device ID into OTP memory",
.args = "<text> [--execute | --dry-run]"
);