feat(core/prodtest): introduce prodtest error codes
What changed, and why it matters
This commit is a feature addition to Trezor's internal production-test firmware. It replaces generic string-based error messages with a structured, numbered error-code system. There is no direct security vulnerability being fixed or introduced; it is a maintainability and diagnostics improvement for factory testing tools.
No immediate security action required. Treat as a normal code-quality/feature commit. Reviewers may optionally verify that the generated `error_codes.json` and header remain in sync and that no command accidentally changed control flow while replacing error calls.
Security signals we found
Large mechanical refactor of error handling in production-test firmware
No changes to cryptographic checks, access control, or secret handling logic
No buffer-size or memory-safety changes observed
No vendor security advisory or CVE references present
Evidence from the diff
The change introduces a generated prodtest_error_codes.h header and error_codes.json registry, plus a Python generator tool and Makefile integration. Across ~30 prodtest command modules, calls like cli_error(cli, CLI_ERROR, ...) are replaced with specific constants such as PRODTEST_ERR_BLE_INIT, PRODTEST_ERR_OTP_EMPTY, etc. The CLI framework itself gains a small set of numeric framework codes (10–14) for invalid command/argument, abort, fatal, and CRC errors. The patch is large but mechanical and does not alter cryptographic, authorization, or runtime behavior beyond error reporting.
Changed components
core/embed/projects/prodtest command modulescore/embed/rtl/cli (CLI framework error codes)core/tools/prodtest_error_codes.py (new generator)Makefile (new `prodtest_error_codes` and `prodtest_error_codes_check` targets)Inspect captured patch +2971 / −376
diff --git a/Makefile b/Makefile
index 3e30f542..a1d13398 100644
--- a/Makefile
+++ b/Makefile
@@ -199,9 +199,15 @@ hsm_keys:
hsm_keys_check:
./core/tools/generate_hsm_keys.py --check
-gen: templates mocks icons protobuf vendorheader solana_templates bootloader_hashes lsgen tropic_model_config hsm_keys ## regenerate auto-generated files from sources
+prodtest_error_codes: ## generate prodtest error codes JSON
+ python3 core/tools/prodtest_error_codes.py
-gen_check: templates_check mocks_check icons_check protobuf_check vendorheader_check solana_templates_check bootloader_hashes_check lsgen_check tropic_model_config_check hsm_keys_check ## check validity of auto-generated files
+prodtest_error_codes_check: ## check prodtest error codes JSON is up to date
+ python3 core/tools/prodtest_error_codes.py --check
+
+gen: templates mocks icons protobuf vendorheader solana_templates bootloader_hashes lsgen tropic_model_config hsm_keys prodtest_error_codes ## regenerate auto-generated files from sources
+
+gen_check: templates_check mocks_check icons_check protobuf_check vendorheader_check solana_templates_check bootloader_hashes_check lsgen_check tropic_model_config_check hsm_keys_check prodtest_error_codes_check ## check validity of auto-generated files
uvlock_check: ## check that uv.lock is up to date
@echo [UVLOCK-CHECK]
diff --git a/core/embed/projects/prodtest/.changelog.d/6829.added b/core/embed/projects/prodtest/.changelog.d/6829.added
new file mode 100644
index 00000000..3a192041
--- /dev/null
+++ b/core/embed/projects/prodtest/.changelog.d/6829.added
@@ -0,0 +1 @@
+Introduce prodtest error codes.
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index acd6db07..8538e155 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -38,22 +38,28 @@ Example:
OK 2.1.7
```
-An `ERROR` response includes an error code and an optional error description enclosed in quotation marks.
+An `ERROR` response includes a numeric error code and an optional error description enclosed in quotation marks.
Example:
```
-ERROR invalid-arg "Expecting x-coordinate."
+ERROR 11 "Expecting x-coordinate."
```
-#### Predefined Error Codes:
+#### Error Codes:
-While commands may define custom error codes as needed, the following are predefined:
+Error codes are non-negative integers split into two groups:
-* `error` - Unspecified error; additional details may be provided in the error description.
-* `invalid-cmd` - The command name is invalid.
-* `invalid-arg` - Invalid command argument.
-* `abort` - Operation aborted by the user (e.g., pressing CTRL+C).
-* `timeout` - The command execution timed out.
+* **Framework codes** are emitted by the CLI engine itself:
+
+ | Code | Name | Meaning |
+ |------|------|---------|
+ | 10 | `CLI_ERROR_INVALID_CMD` | The command name is invalid. |
+ | 11 | `CLI_ERROR_INVALID_ARG` | Invalid command argument. |
+ | 12 | `CLI_ERROR_ABORT` | Operation aborted by the user (e.g., pressing CTRL+C). |
+ | 13 | `CLI_ERROR_FATAL` | Unspecified fatal error; additional details may be provided in the description. |
+ | 14 | `CLI_ERROR_INVALID_CRC` | The CRC checksum of the command is missing or invalid. |
+
+* **Command-specific codes** (≥ 1000) are returned by individual command handlers, with each module owning a numeric range. The authoritative list of codes, their symbolic names, and owning modules is maintained in [`error_codes.json`](error_codes.json).
### Progress response
@@ -276,7 +282,7 @@ The `button-test` command tests the functionality of the device's hardware butto
* `button` specifies the expected button or combination of buttons, with possible values: `left`, `right`, `left+right`, `power`.
* `timeout` specifies the timeout duration in milliseconds
-If the specified button or button combination is not detected within the timeout, the command will respond with `timeout` error.
+If the specified button or button combination is not detected within the timeout, the command will respond with a timeout error (`4010` `PRODTEST_ERR_BUTTON_PRESS_TIMEOUT`).
Example (to wait for 5 seconds for the left button):
```
@@ -447,7 +453,7 @@ Starts a drawing canvas, where user can draw with finger on pen. Canvas is exite
touch-draw
# Starting drawing canvas...
# Press CTRL+C for exit.
-ERROR abort
+ERROR 12
```
### touch-test
@@ -458,7 +464,7 @@ Tests the functionality of the display's touch screen. It draws a filled rectang
* `quadrant` - A value between 0 and 3, determining the quadrant where the rectangle will be drawn.
* `timeout` - The timeout duration in milliseconds.
-If the display is not touched within the specified timeout, the command will return a `timeout` error.
+If the display is not touched within the specified timeout, the command will return a timeout error (`19011` `PRODTEST_ERR_TOUCH_QUADRANT_TIMEOUT`).
The command does not check whether the touch point lies within the quadrant or not. It only returns the x and y coordinate of the touch point.
@@ -481,7 +487,7 @@ Tests the functionality of the display's touch screen by drawing a filled rectan
* `height` - The height of the rectangle.
* `timeout` - The timeout duration in milliseconds.
-If the display is not touched within the specified timeout, the command returns a `timeout` error.
+If the display is not touched within the specified timeout, the command returns a timeout error (`19012` `PRODTEST_ERR_TOUCH_CUSTOM_TIMEOUT`).
The device reports touch events, including coordinates and timestamps (in milliseconds). The correctness of the touch point is not validated and is left to the test equipment.
@@ -507,7 +513,7 @@ Tests the functionality of the display's touch screen by verifying that no touch
* `timeout` - The duration to wait, in milliseconds, during which no touch input should be detected.
-If any touch activity is detected within the specified timeout, the command returns an error.
+If any touch activity is detected within the specified timeout, the command returns an error (`19013` `PRODTEST_ERR_TOUCH_UNEXPECTED_ACTIVITY`).
Example (wait 10 seconds to ensure no touch input is detected):
```
@@ -549,7 +555,7 @@ touch-test-sensitivity 12
# Setting touch controller sensitivity to 12...
# Running touch controller test...
# Press CTRL+C for exit.
-ERROR abort
+ERROR 12
```
### touch-version
@@ -568,8 +574,8 @@ Initiates a basic test of the SD card by writing a few blocks of data, reading t
Possible error return codes are:
-- `no-card` - Indicates that no SD card is present
-- `error` - An I/O error occured (with additional details provided in the description field)
+- `14010` (`PRODTEST_ERR_SDCARD_NO_CARD`) - Indicates that no SD card is present
+- `14011`–`14015` - An I/O error occurred (with additional details provided in the description field)
Example:
```
@@ -627,14 +633,14 @@ OK
### otp-batch-read
Retrieves the batch string from the device's OTP memory. The batch string identifies the model and production batch of the device.
-If the OTP memory has not been written yet, it returns error code `no-data`.
+If the OTP memory has not been written yet, it returns error code `10012` (`PRODTEST_ERR_OTP_EMPTY`).
Example:
```
otp-batch-read
# Reading device OTP memory...
# Bytes read: <hexadecimal string>
-ERROR no-data "OTP block is empty."
+ERROR 10012 "OTP block is empty."
```
### otp-batch-write
@@ -661,14 +667,14 @@ otp-batch-write T2B1-231231 --dry-run
Retrieves the device's serial number from the device's OTP memory. The device serial number is unique for each device.
A QR code with the serial number is displayed on the prodtest screen and printed on the packaging.
-If the OTP memory has not been written yet, it returns error code `no-data`.
+If the OTP memory has not been written yet, it returns error code `10012` (`PRODTEST_ERR_OTP_EMPTY`).
Example:
```
otp-device-sn-read
# Reading device OTP memory...
# Bytes read: <hexadecimal string>
-ERROR no-data "OTP block is empty."
+ERROR 10012 "OTP block is empty."
```
### otp-device-sn-write
@@ -1129,7 +1135,7 @@ the following criteria to pass the test
- Every sample NTC temperature is within range <-10, 65> °C
In case any sample fails the test, the line is marked with `!` and test
-ends up with `ERROR error "Battery test failed."`.
+ends up with `ERROR 12020 "Battery test failed."` (`PRODTEST_ERR_PM_BATTERY_TEST`).
Example:
```
diff --git a/core/embed/projects/prodtest/cmd/common.c b/core/embed/projects/prodtest/cmd/common.c
index 864c66f2..7ed4cf65 100644
--- a/core/embed/projects/prodtest/cmd/common.c
+++ b/core/embed/projects/prodtest/cmd/common.c
@@ -224,7 +224,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
const uint8_t** authority_key_digest) {
DER_ITEM extensions = {0};
if (!get_cert_extensions(tbs_cert, &extensions)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_EXTENSIONS,
"get_authority_key_digest, extensions not found.");
return false;
}
@@ -234,7 +234,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
if (!get_extension_value(OID_AUTHORITY_KEY_IDENTIFIER,
sizeof(OID_AUTHORITY_KEY_IDENTIFIER), &extensions,
&extension_value)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_NOT_FOUND,
"get_authority_key_digest, authority key identifier extension "
"not found.");
return false;
@@ -244,7 +244,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
DER_ITEM auth_key_id = {0};
if (!der_read_item_expected(&extension_value.buf, DER_SEQUENCE,
&auth_key_id)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_EXTNVALUE,
"get_authority_key_digest, failed to open authority key "
"identifier extnValue.");
return false;
@@ -254,7 +254,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
DER_ITEM key_id = {0};
if (!der_read_item_expected(&auth_key_id.buf, DER_X509_KEY_IDENTIFIER,
&key_id)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_FIELD,
"get_authority_key_digest, failed to find keyIdentifier field.");
return false;
}
@@ -262,7 +262,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
// Return the pointer to the keyIdentifier data.
if (buffer_remaining(&key_id.buf) != SHA1_DIGEST_LENGTH ||
!buffer_ptr(&key_id.buf, authority_key_digest)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_LEN,
"get_authority_key_digest, invalid length of keyIdentifier.");
return false;
}
@@ -442,7 +442,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
cert_count += 1;
DER_ITEM cert = {0};
if (!der_read_item_expected(&chain_reader, DER_SEQUENCE, &cert)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_CERT,
"check_device_cert_chain, der_read_item 1, cert %d.",
cert_count);
return false;
@@ -451,7 +451,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// Read the tbsCertificate.
DER_ITEM tbs_cert = {0};
if (!der_read_item_expected(&cert.buf, DER_SEQUENCE, &tbs_cert)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS,
"check_device_cert_chain, der_read_item 2, cert %d.",
cert_count);
return false;
@@ -461,7 +461,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
DER_ITEM der_item = {0};
for (int i = 0; i < 5; ++i) {
if (!der_read_item(&tbs_cert.buf, &der_item)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS_PRELUDE,
"check_device_cert_chain, der_read_item 3, cert %d.",
cert_count);
return false;
@@ -471,7 +471,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// Read the subject.
DER_ITEM subject = {0};
if (!der_read_item_expected(&tbs_cert.buf, DER_SEQUENCE, &subject)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SUBJECT,
"check_device_cert_chain, der_read_item 4, cert %d.",
cert_count);
return false;
@@ -487,7 +487,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
common_name_size != sizeof(SUBJECT_COMMON_NAME) ||
memcmp(common_name, SUBJECT_COMMON_NAME,
sizeof(SUBJECT_COMMON_NAME)) != 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_COMMON_NAME,
"check_device_cert_chain, invalid common name.");
return false;
}
@@ -499,7 +499,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
if (!unit_properties_get_sn(device_sn, sizeof(device_sn),
&device_sn_size) ||
device_sn_size == 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_DEVICE_SN,
"check_device_cert_chain, device_sn not set.");
}
@@ -508,13 +508,13 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
if (!get_name_attribute(&subject, OID_SERIAL_NUMBER,
sizeof(OID_SERIAL_NUMBER), &subject_sn,
&subject_sn_size)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SERIAL_NUM,
"check_device_cert_chain, serialNumber not set.");
}
if (subject_sn_size != device_sn_size ||
memcmp(subject_sn, device_sn, device_sn_size) != 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SN_MISMATCH,
"check_device_cert_chain, serial number mismatch.");
return false;
}
@@ -524,7 +524,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// Read the Subject Public Key Info.
DER_ITEM pub_key_info = {0};
if (!der_read_item_expected(&tbs_cert.buf, DER_SEQUENCE, &pub_key_info)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SPKI,
"check_device_cert_chain, der_read_item 5, cert %d.",
cert_count);
return false;
@@ -534,7 +534,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
DER_ITEM alg = {0};
if (!der_read_item_expected(&pub_key_info.buf, DER_SEQUENCE, &alg) ||
!get_algorithm(&alg, &alg_id)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ALGORITHM,
"check_device_cert_chain, reading algorithm, cert %d.",
cert_count);
return false;
@@ -545,7 +545,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
uint8_t unused_bits = 0;
if (!der_read_item_expected(&pub_key_info.buf, DER_BIT_STRING,
&pub_key_val)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_PUBKEY_BITS,
"check_device_cert_chain, der_read_item 6, cert %d.",
cert_count);
return false;
@@ -553,7 +553,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
if (!buffer_get(&pub_key_val.buf, &unused_bits) ||
!buffer_ptr(&pub_key_val.buf, &pub_key)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_PUBKEY,
"check_device_cert_chain, reading public key, cert %d.",
cert_count);
return false;
@@ -563,7 +563,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// Verify the previous signature.
if (!verify_signature(alg_id, pub_key, pub_key_size, sig, sig_size, message,
message_size)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_VERIFY_SIG,
"check_device_cert_chain, verify_signature, cert %d.",
cert_count);
return false;
@@ -583,7 +583,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// skip the signatureAlgorithm
DER_ITEM sig_alg = {0};
if (!der_read_item_expected(&cert.buf, DER_SEQUENCE, &sig_alg)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SIG_ALG,
"check_device_cert_chain, der_read_item 7, cert %d.", "%d.",
cert_count);
return false;
@@ -594,7 +594,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
if (!der_read_item_expected(&cert.buf, DER_BIT_STRING, &sig_val) ||
!buffer_get(&sig_val.buf, &unused_bits) || unused_bits != 0 ||
!buffer_ptr(&sig_val.buf, &sig)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SIG_VALUE,
"check_device_cert_chain, reading signatureValue, cert %d.",
cert_count);
return false;
@@ -612,7 +612,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
uint8_t decoded_sig[64] = {0};
if (ecdsa_sig_from_der(sig, sig_size, decoded_sig) != 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_DER,
"check_device_cert_chain, ecdsa_sig_from_der root.");
return false;
}
@@ -632,7 +632,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
}
}
if (!matches) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_ROOT,
"check_device_cert_chain, ecdsa_verify_digest root.");
return false;
}
@@ -643,7 +643,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
const char msg[] =
"check_device_cert_chain, failed to get root public key.";
#if PRODUCTION
- cli_error(cli, CLI_ERROR, msg);
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_KEY, msg);
return false;
#else
// In non-production mode we succeed and write the certificate even if the
@@ -656,7 +656,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
// Verify the last signature.
if (!verify_signature(alg_id, pub_key, pub_key_size, sig, sig_size, message,
message_size)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_SIG,
"check_device_cert_chain, verify_signature, cert %d.",
cert_count);
return false;
@@ -708,7 +708,8 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
}
if (!binary_update_in_progress) {
- cli_error(cli, CLI_ERROR, "Update not started. Use 'begin' first.");
+ cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_NOT_STARTED,
+ "Update not started. Use 'begin' first.");
goto cleanup;
}
@@ -732,13 +733,14 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
}
if (binary_len == 0) {
- cli_error(cli, CLI_ERROR, "No data received");
+ cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_NO_DATA, "No data received");
goto cleanup;
}
if (!finalize(binary_buffer, binary_len)) {
binary_len = 0;
- cli_error(cli, CLI_ERROR, "Error while finalizing the update");
+ cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_FINALIZE,
+ "Error while finalizing the update");
goto cleanup;
}
@@ -750,7 +752,8 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
binary_update_in_progress = false;
} else {
- cli_error(cli, CLI_ERROR, "Unknown phase '%s' (begin|chunk|end)", phase);
+ cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_UNKNOWN_PHASE,
+ "Unknown phase '%s' (begin|chunk|end)", phase);
goto cleanup;
}
diff --git a/core/embed/projects/prodtest/cmd/common.h b/core/embed/projects/prodtest/cmd/common.h
index 0b1f8e0a..19203973 100644
--- a/core/embed/projects/prodtest/cmd/common.h
+++ b/core/embed/projects/prodtest/cmd/common.h
@@ -21,6 +21,8 @@
#include <rtl/cli.h>
+#include "prodtest_error_codes.h"
+
#define CHALLENGE_SIZE 16
bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
diff --git a/core/embed/projects/prodtest/cmd/prodtest_backup_ram.c b/core/embed/projects/prodtest/cmd/prodtest_backup_ram.c
index c61ce2e9..460004b6 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_backup_ram.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_backup_ram.c
@@ -26,6 +26,8 @@
#include <sec/backup_ram.h>
#include <sys/systick.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_backup_ram_list(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -33,7 +35,8 @@ static void prodtest_backup_ram_list(cli_t* cli) {
}
if (!backup_ram_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_LIST_INIT,
+ "Failed to initialize backup RAM");
return;
}
@@ -45,7 +48,8 @@ static void prodtest_backup_ram_list(cli_t* cli) {
if (backup_ram_read(key, NULL, 0, &data_size)) {
cli_trace(cli, "Key #%d: %d bytes", key, data_size);
} else {
- cli_error(cli, CLI_ERROR, "Failed to read key #%d info", key);
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_INFO_READ,
+ "Failed to read key #%d info", key);
return;
}
key++;
@@ -68,7 +72,8 @@ static void prodtest_backup_ram_erase(cli_t* cli) {
}
if (!backup_ram_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_ERASE_INIT,
+ "Failed to initialize backup RAM");
return;
}
@@ -90,19 +95,22 @@ static void prodtest_backup_ram_read(cli_t* cli) {
}
if (!backup_ram_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_READ_INIT,
+ "Failed to initialize backup RAM");
return;
}
if (!backup_ram_read(key, NULL, 0, NULL)) {
- cli_error(cli, CLI_ERROR, "Key #%d not found", key);
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_NOT_FOUND, "Key #%d not found",
+ key);
return;
}
uint8_t data[BACKUP_RAM_MAX_KEY_DATA_SIZE];
size_t data_size = 0;
if (!backup_ram_read(key, data, sizeof(data), &data_size)) {
- cli_error(cli, CLI_ERROR, "Failed to read the key #%d", key);
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_READ,
+ "Failed to read the key #%d", key);
return;
}
@@ -114,7 +122,7 @@ static void prodtest_backup_ram_read(cli_t* cli) {
char block_hex[16 * 2 + 1];
if (!cstr_encode_hex(block_hex, sizeof(block_hex), &data[offset],
block_size)) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_HEX_ENCODE, "Buffer too small.");
return;
}
cli_trace(cli, "%04x: %s", offset, block_hex);
@@ -149,21 +157,24 @@ static void prodtest_backup_ram_write(cli_t* cli) {
if (cli_has_arg(cli, "hex-data")) {
if (!cli_arg_hex(cli, "hex-data", data, sizeof(data), &len)) {
if (len == sizeof(data)) {
- cli_error(cli, CLI_ERROR, "Data too long.");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_DATA_TOO_LONG, "Data too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
}
if (!backup_ram_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_WRITE_INIT,
+ "Failed to initialize backup RAM");
return;
}
if (!backup_ram_write(key, type, data, len)) {
- cli_error(cli, CLI_ERROR, "Failed to write key #%d", key);
+ cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_WRITE, "Failed to write key #%d",
+ key);
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_ble.c b/core/embed/projects/prodtest/cmd/prodtest_ble.c
index 17a8f3a0..fe26cd74 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_ble.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_ble.c
@@ -30,6 +30,8 @@
#include <sys/systick.h>
#include <sys/systimer.h>
+#include "prodtest_error_codes.h"
+
void ble_timer_cb(void* context) {
ble_event_t e = {0};
@@ -48,7 +50,7 @@ void ble_timer_cb(void* context) {
static bool ensure_ble_init(cli_t* cli) {
cli_trace(cli, "Initializing the BLE...");
if (!ble_init()) {
- cli_error(cli, CLI_ERROR, "Cannot initialize BLE.");
+ cli_error(cli, PRODTEST_ERR_BLE_INIT, "Cannot initialize BLE.");
return false;
}
@@ -57,7 +59,7 @@ static bool ensure_ble_init(cli_t* cli) {
if (timer == NULL) {
timer = systimer_create(ble_timer_cb, NULL);
if (timer == NULL) {
- cli_error(cli, CLI_ERROR, "Cannot create timer.");
+ cli_error(cli, PRODTEST_ERR_BLE_TIMER_CREATE, "Cannot create timer.");
return false;
}
systimer_set_periodic(timer, 10);
@@ -83,7 +85,8 @@ static void prodtest_ble_adv_start(cli_t* cli) {
ble_set_static_mac(true);
if (!ble_enter_pairing_mode((const uint8_t*)name, name_len)) {
- cli_error(cli, CLI_ERROR, "Could not start advertising.");
+ cli_error(cli, PRODTEST_ERR_BLE_ENTER_PAIRING_MODE,
+ "Could not start advertising.");
return;
}
@@ -101,7 +104,8 @@ static void prodtest_ble_adv_start(cli_t* cli) {
}
if (!result) {
- cli_error(cli, CLI_ERROR, "Could not start advertising.");
+ cli_error(cli, PRODTEST_ERR_BLE_ADV_START_TIMEOUT,
+ "Could not start advertising.");
return;
}
@@ -120,7 +124,7 @@ static void prodtest_ble_adv_stop(cli_t* cli) {
}
if (!ble_switch_off()) {
- cli_error(cli, CLI_ERROR, "Could not stop advertising.");
+ cli_error(cli, PRODTEST_ERR_BLE_SWITCH_OFF, "Could not stop advertising.");
return;
}
@@ -138,7 +142,8 @@ static void prodtest_ble_adv_stop(cli_t* cli) {
}
if (!result) {
- cli_error(cli, CLI_ERROR, "Could not stop advertising.");
+ cli_error(cli, PRODTEST_ERR_BLE_ADV_STOP_TIMEOUT,
+ "Could not stop advertising.");
return;
}
@@ -159,7 +164,7 @@ static void prodtest_ble_info(cli_t* cli) {
bt_le_addr_t mac = {0};
if (!ble_get_mac(&mac)) {
- cli_error(cli, CLI_ERROR, "Could not read MAC.");
+ cli_error(cli, PRODTEST_ERR_BLE_MAC_READ, "Could not read MAC.");
return;
}
@@ -199,7 +204,7 @@ static void prodtest_ble_erase_bonds_cmd(cli_t* cli) {
ble_get_state(&state);
if (!state.state_known) {
- cli_error(cli, CLI_ERROR, "BLE state unknown.");
+ cli_error(cli, PRODTEST_ERR_BLE_STATE_UNKNOWN, "BLE state unknown.");
}
if (state.peer_count == 0) {
@@ -208,7 +213,7 @@ static void prodtest_ble_erase_bonds_cmd(cli_t* cli) {
}
if (!prodtest_ble_erase_bonds(cli)) {
- cli_error(cli, CLI_ERROR, "Could not erase bonds.");
+ cli_error(cli, PRODTEST_ERR_BLE_BONDS_ERASE, "Could not erase bonds.");
}
cli_trace(cli, "Erased %d bonds.", state.peer_count);
@@ -249,7 +254,7 @@ static void prodtest_ble_unpair(cli_t* cli) {
uint32_t index;
if (!cli_arg_uint32(cli, "index", &index)) {
- cli_error(cli, CLI_ERROR, "Invalid index.");
+ cli_error(cli, PRODTEST_ERR_BLE_UNPAIR_INDEX_PARSE, "Invalid index.");
return;
}
@@ -261,13 +266,13 @@ static void prodtest_ble_unpair(cli_t* cli) {
uint8_t cnt = ble_get_bond_list(bonds, BLE_MAX_BONDS);
if (index > cnt || index < 1) {
- cli_error(cli, CLI_ERROR, "Invalid index.");
+ cli_error(cli, PRODTEST_ERR_BLE_UNPAIR_INDEX_RANGE, "Invalid index.");
return;
}
bt_le_addr_t* addr = &bonds[index - 1];
if (!ble_unpair(addr)) {
- cli_error(cli, CLI_ERROR, "Could not unpair.");
+ cli_error(cli, PRODTEST_ERR_BLE_UNPAIR, "Could not unpair.");
return;
}
@@ -332,7 +337,7 @@ static void prodtest_ble_radio_test_cmd(cli_t* cli) {
// Initialize UART
if (HAL_UART_Init(&huart) != HAL_OK) {
- cli_error(cli, CLI_ERROR, "Could not initialize UART.");
+ cli_error(cli, PRODTEST_ERR_BLE_UART_INIT, "Could not initialize UART.");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_bootloader.c b/core/embed/projects/prodtest/cmd/prodtest_bootloader.c
index 1eaef139..13ef9579 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_bootloader.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_bootloader.c
@@ -46,7 +46,8 @@ static void prodtest_bootloader_version(cli_t *cli) {
if (hdr == NULL) {
mpu_restore(mpu_mode);
- cli_error(cli, CLI_ERROR, "No valid bootloader header found.");
+ cli_error(cli, PRODTEST_ERR_BOOTLOADER_NO_AUTH_HEADER,
+ "No valid bootloader header found.");
return;
}
@@ -69,7 +70,8 @@ static void prodtest_bootloader_version(cli_t *cli) {
if (header != NULL) {
v = header->version;
} else {
- cli_error(cli, CLI_ERROR, "No valid bootloader header found.");
+ cli_error(cli, PRODTEST_ERR_BOOTLOADER_NO_IMAGE_HEADER,
+ "No valid bootloader header found.");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_button.c b/core/embed/projects/prodtest/cmd/prodtest_button.c
index c8ac5700..54350143 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_button.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_button.c
@@ -25,6 +25,8 @@
#include <rtl/cli.h>
#include <sys/systick.h>
+#include "prodtest_error_codes.h"
+
static void test_single_button(cli_t* cli, uint32_t timeout, button_t btn) {
uint32_t expire_time = ticks_timeout(timeout);
@@ -34,7 +36,7 @@ static void test_single_button(cli_t* cli, uint32_t timeout, button_t btn) {
while (!button_get_event(&btn_event) || (btn_event.button != btn) ||
(btn_event.event_type != BTN_EVENT_DOWN)) {
if (ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_BUTTON_PRESS_TIMEOUT, "Timeout");
return;
}
@@ -48,7 +50,7 @@ static void test_single_button(cli_t* cli, uint32_t timeout, button_t btn) {
while (!button_get_event(&btn_event) || (btn_event.button != btn) ||
(btn_event.event_type != BTN_EVENT_UP)) {
if (ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_BUTTON_RELEASE_TIMEOUT, "Timeout");
return;
}
@@ -70,7 +72,7 @@ static void test_button_combination(cli_t* cli, uint32_t timeout, button_t btn1,
if (button_is_down(btn1) && button_is_down(btn2)) {
break;
} else if (ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_BUTTON_COMBO_PRESS_TIMEOUT, "Timeout");
return;
} else if (cli_aborted(cli)) {
return;
@@ -83,7 +85,7 @@ static void test_button_combination(cli_t* cli, uint32_t timeout, button_t btn1,
if (!button_is_down(btn1) && !button_is_down(btn2)) {
break;
} else if (ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_BUTTON_COMBO_RELEASE_TIMEOUT, "Timeout");
return;
} else if (cli_aborted(cli)) {
return;
diff --git a/core/embed/projects/prodtest/cmd/prodtest_haptic.c b/core/embed/projects/prodtest/cmd/prodtest_haptic.c
index d3f71722..4fa95cf8 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_haptic.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_haptic.c
@@ -24,6 +24,8 @@
#include <io/haptic.h>
#include <rtl/cli.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_haptic_test(cli_t* cli) {
uint32_t duration_ms = 0; // ms
uint32_t amplitude = 100; // default amplitude
@@ -49,7 +51,8 @@ static void prodtest_haptic_test(cli_t* cli) {
status = haptic_init();
if (ts_error(status)) {
- cli_error(cli, CLI_ERROR, "Haptic driver initialization failed.");
+ cli_error(cli, PRODTEST_ERR_HAPTIC_INIT,
+ "Haptic driver initialization failed.");
return;
}
@@ -58,7 +61,7 @@ static void prodtest_haptic_test(cli_t* cli) {
status = haptic_play_custom(amplitude, duration_ms);
if (ts_error(status)) {
- cli_error(cli, CLI_ERROR, "Haptic feedback test failed.");
+ cli_error(cli, PRODTEST_ERR_HAPTIC_TEST, "Haptic feedback test failed.");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_manufacturing_lock.c b/core/embed/projects/prodtest/cmd/prodtest_manufacturing_lock.c
index deb762e5..3c1e6ff4 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_manufacturing_lock.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_manufacturing_lock.c
@@ -25,6 +25,8 @@
#include <sec/unit_properties.h>
#include <sys/flash_otp.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_manufacturing_lock_read(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -64,7 +66,8 @@ static void prodtest_manufacturing_lock_write(cli_t* cli) {
}
if (sectrue == flash_otp_is_locked(FLASH_OTP_BLOCK_MANUFACTURING_LOCK)) {
- cli_error(cli, CLI_ERROR_LOCKED, "Manufacturing lock is already set.");
+ cli_error(cli, PRODTEST_ERR_MANUF_LOCK_ALREADY_SET,
+ "Manufacturing lock is already set.");
return;
}
@@ -85,14 +88,16 @@ static void prodtest_manufacturing_lock_write(cli_t* cli) {
if (!dry_run) {
if (sectrue != flash_otp_write(FLASH_OTP_BLOCK_MANUFACTURING_LOCK, 0, block,
sizeof(block))) {
- cli_error(cli, CLI_ERROR, "Failed to write OTP block.");
+ cli_error(cli, PRODTEST_ERR_MANUF_LOCK_OTP_WRITE,
+ "Failed to write OTP block.");
return;
}
cli_trace(cli, "Locking OTP block...");
if (sectrue != flash_otp_lock(FLASH_OTP_BLOCK_MANUFACTURING_LOCK)) {
- cli_error(cli, CLI_ERROR, "Failed to lock the OTP block.");
+ cli_error(cli, PRODTEST_ERR_MANUF_LOCK_OTP_LOCK,
+ "Failed to lock the OTP block.");
return;
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_nfc.c b/core/embed/projects/prodtest/cmd/prodtest_nfc.c
index e289ebdb..4cd85179 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_nfc.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_nfc.c
@@ -25,6 +25,8 @@
#include <rtl/cli.h>
#include <sys/systick.h>
+#include "prodtest_error_codes.h"
+
static nfc_dev_info_t dev_info = {0};
static void prodtest_nfc_read_card(cli_t* cli) {
@@ -48,7 +50,7 @@ static void prodtest_nfc_read_card(cli_t* cli) {
nfc_status_t ret = nfc_init();
if (ret != NFC_OK) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
+ cli_error(cli, PRODTEST_ERR_NFC_READ_CARD_INIT, "NFC init failed");
goto cleanup;
} else {
if (timeout_set) {
@@ -60,12 +62,12 @@ static void prodtest_nfc_read_card(cli_t* cli) {
if (NFC_OK != nfc_register_tech(NFC_POLLER_TECH_A | NFC_POLLER_TECH_B |
NFC_POLLER_TECH_F | NFC_POLLER_TECH_V)) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC tech registration failed");
+ cli_error(cli, PRODTEST_ERR_NFC_TECH_REG, "NFC tech registration failed");
goto cleanup;
}
if (NFC_OK != nfc_activate_stm()) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC activation failed");
+ cli_error(cli, PRODTEST_ERR_NFC_ACTIVATION, "NFC activation failed");
goto cleanup;
}
@@ -74,14 +76,14 @@ static void prodtest_nfc_read_card(cli_t* cli) {
while (true) {
if (timeout_set && ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
+ cli_error(cli, PRODTEST_ERR_NFC_READ_CARD_TIMEOUT, "NFC timeout");
goto cleanup;
}
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
if (nfc_status != NFC_OK) {
- cli_error(cli, CLI_ERROR, "NFC error");
+ cli_error(cli, PRODTEST_ERR_NFC_READ_CARD_ERROR, "NFC error");
goto cleanup;
}
@@ -113,7 +115,7 @@ static void prodtest_nfc_read_card(cli_t* cli) {
cli_trace(cli, "NFC Type UNKNOWN");
break;
default:
- cli_error(cli, CLI_ERROR_ABORT, "NFC ERROR Unexpected");
+ cli_error(cli, PRODTEST_ERR_NFC_UNEXPECTED, "NFC ERROR Unexpected");
goto cleanup;
}
@@ -160,7 +162,7 @@ static void prodtest_nfc_emulate_card(cli_t* cli) {
nfc_status_t ret = nfc_init();
if (ret != NFC_OK) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
+ cli_error(cli, PRODTEST_ERR_NFC_EMULATE_INIT, "NFC init failed");
goto cleanup;
} else {
if (timeout_set) {
@@ -180,7 +182,7 @@ static void prodtest_nfc_emulate_card(cli_t* cli) {
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
if (nfc_status != NFC_OK) {
- cli_error(cli, CLI_ERROR, "NFC error");
+ cli_error(cli, PRODTEST_ERR_NFC_EMULATE_ERROR, "NFC error");
goto cleanup;
}
@@ -219,7 +221,7 @@ static void prodtest_nfc_write_card(cli_t* cli) {
nfc_status_t ret = nfc_init();
if (ret != NFC_OK) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
+ cli_error(cli, PRODTEST_ERR_NFC_WRITE_CARD_INIT, "NFC init failed");
goto cleanup;
} else {
if (timeout_set) {
@@ -240,14 +242,14 @@ static void prodtest_nfc_write_card(cli_t* cli) {
while (true) {
if (timeout_set && ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
+ cli_error(cli, PRODTEST_ERR_NFC_WRITE_CARD_TIMEOUT, "NFC timeout");
goto cleanup;
}
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
if (nfc_status != NFC_OK) {
- cli_error(cli, CLI_ERROR_FATAL, "NFC error");
+ cli_error(cli, PRODTEST_ERR_NFC_WRITE_CARD_ERROR, "NFC error");
goto cleanup;
}
@@ -255,7 +257,8 @@ static void prodtest_nfc_write_card(cli_t* cli) {
nfc_dev_read_info(&dev_info);
if (dev_info.type != NFC_DEV_TYPE_A) {
- cli_error(cli, CLI_ERROR_ABORT, "Only NFC type A cards supported");
+ cli_error(cli, PRODTEST_ERR_NFC_TYPE_A_ONLY,
+ "Only NFC type A cards supported");
goto cleanup;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_nrf.c b/core/embed/projects/prodtest/cmd/prodtest_nrf.c
index 05b32f6d..a8f459f4 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_nrf.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_nrf.c
@@ -31,31 +31,32 @@
static void prodtest_nrf_communication(cli_t* cli) {
cli_trace(cli, "Testing SPI communication...");
if (!nrf_test_spi_comm()) {
- cli_error(cli, CLI_ERROR, "SPI communication failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_SPI_COMM, "SPI communication failed.");
return;
}
cli_trace(cli, "Testing UART communication...");
if (!nrf_test_uart_comm()) {
- cli_error(cli, CLI_ERROR, "UART communication failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_UART_COMM, "UART communication failed.");
return;
}
cli_trace(cli, "Testing reset..");
if (!nrf_test_reset()) {
- cli_error(cli, CLI_ERROR, "Reset failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_RESET, "Reset failed.");
return;
}
cli_trace(cli, "Testing GPIO stay in bootloader...");
if (!nrf_test_gpio_stay_in_bld()) {
- cli_error(cli, CLI_ERROR, "Stay in bootloader GPIO failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_BOOTLOADER_GPIO,
+ "Stay in bootloader GPIO failed.");
return;
}
cli_trace(cli, "Testing GPIO reserved...");
if (!nrf_test_gpio_reserved()) {
- cli_error(cli, CLI_ERROR, "Reserved GPIO failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_RESERVED_GPIO, "Reserved GPIO failed.");
return;
}
@@ -65,7 +66,7 @@ static void prodtest_nrf_communication(cli_t* cli) {
static void prodtest_nrf_version(cli_t* cli) {
nrf_info_t info = {0};
if (!nrf_get_info(&info)) {
- cli_error(cli, CLI_ERROR, "Could not read version.");
+ cli_error(cli, PRODTEST_ERR_NRF_VERSION_READ, "Could not read version.");
return;
}
@@ -94,7 +95,7 @@ static void prodtest_nrf_pair(cli_t* cli) {
return;
}
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_NRF_PAIR_SECRETS_LOCKED,
"Secrets sector is locked. Pairing is not allowed.");
return;
}
@@ -102,7 +103,7 @@ static void prodtest_nrf_pair(cli_t* cli) {
if (nrf_test_pair()) {
cli_ok(cli, "");
} else {
- cli_error(cli, CLI_ERROR, "Pairing failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_PAIR_FAILED, "Pairing failed.");
}
}
@@ -115,7 +116,8 @@ static void prodtest_nrf_verify_pairing(cli_t* cli) {
if (nrf_authenticate()) {
cli_ok(cli, "");
} else {
- cli_error(cli, CLI_ERROR, "Pairing verification failed.");
+ cli_error(cli, PRODTEST_ERR_NRF_PAIR_VERIFY,
+ "Pairing verification failed.");
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_optiga.c b/core/embed/projects/prodtest/cmd/prodtest_optiga.c
index a37592d8..b3cc2854 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_optiga.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_optiga.c
@@ -67,7 +67,7 @@ static bool set_metadata(cli_t* cli, uint16_t oid,
sizeof(serialized), &size);
if (OPTIGA_SUCCESS != ret) {
if (report_error) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_OPTIGA_SET_META_SERIALIZE,
"optiga_serialize_metadata error %d for OID 0x%04x.", ret, oid);
}
return false;
@@ -79,8 +79,8 @@ static bool set_metadata(cli_t* cli, uint16_t oid,
optiga_get_data_object(oid, true, serialized, sizeof(serialized), &size);
if (OPTIGA_SUCCESS != ret) {
if (report_error) {
- cli_error(cli, CLI_ERROR, "optiga_get_metadata error %d for OID 0x%04x.",
- ret, oid);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_SET_META_GET,
+ "optiga_get_metadata error %d for OID 0x%04x.", ret, oid);
}
return false;
}
@@ -89,14 +89,16 @@ static bool set_metadata(cli_t* cli, uint16_t oid,
ret = optiga_parse_metadata(serialized, size, &metadata_stored);
if (OPTIGA_SUCCESS != ret) {
if (report_error) {
- cli_error(cli, CLI_ERROR, "optiga_parse_metadata error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_SET_META_PARSE,
+ "optiga_parse_metadata error %d.", ret);
}
return false;
}
if (!optiga_compare_metadata(metadata, &metadata_stored)) {
if (report_error) {
- cli_error(cli, CLI_ERROR, "optiga_compare_metadata failed.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_SET_META_COMPARE,
+ "optiga_compare_metadata failed.");
}
return false;
}
@@ -114,7 +116,7 @@ void prodtest_optiga_pair(cli_t* cli) {
// Load the pairing secret from the flash memory.
if (sectrue != secret_key_optiga_pairing(pairing_secret)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PAIR_SECRET,
"`secret_key_optiga_pairing` failed. You have to call "
"`secrets_write` first.");
goto cleanup;
@@ -138,14 +140,16 @@ void prodtest_optiga_pair(cli_t* cli) {
if (OPTIGA_SUCCESS != optiga_set_data_object(OID_KEY_PAIRING, false,
pairing_secret,
sizeof(pairing_secret))) {
- cli_error(cli, CLI_ERROR, "`optiga_set_data_object` failed.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PAIR_SET_DATA,
+ "`optiga_set_data_object` failed.");
goto cleanup;
}
// Execute the handshake to verify that the secret is stored in Optiga.
if (OPTIGA_SUCCESS !=
optiga_sec_chan_handshake(pairing_secret, sizeof(pairing_secret))) {
- cli_error(cli, CLI_ERROR, "`optiga_sec_chan_handshake` failed.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PAIR_HANDSHAKE,
+ "`optiga_sec_chan_handshake` failed.");
goto cleanup;
}
}
@@ -181,8 +185,8 @@ static void prodtest_optiga_lock(cli_t* cli) {
optiga_result ret =
optiga_set_data_object(OID_TRUST_ANCHOR, false, (const uint8_t*)"\0", 1);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_set_data error %d for 0x%04x.", ret,
- OID_TRUST_ANCHOR);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_LOCK_TRUST_ANCHOR,
+ "optiga_set_data error %d for 0x%04x.", ret, OID_TRUST_ANCHOR);
return;
}
@@ -258,8 +262,8 @@ optiga_locked_status get_optiga_locked_status(cli_t* cli) {
optiga_get_data_object(oids[i], true, metadata_buffer,
sizeof(metadata_buffer), &metadata_size);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_get_metadata error %d for OID 0x%04x.",
- ret, oids[i]);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_STATUS_SERIALIZE,
+ "optiga_get_metadata error %d for OID 0x%04x.", ret, oids[i]);
return OPTIGA_LOCKED_ERROR;
}
@@ -267,7 +271,8 @@ optiga_locked_status get_optiga_locked_status(cli_t* cli) {
ret =
optiga_parse_metadata(metadata_buffer, metadata_size, &stored_metadata);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_parse_metadata error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_STATUS_PARSE,
+ "optiga_parse_metadata error %d.", ret);
return OPTIGA_LOCKED_ERROR;
}
@@ -311,8 +316,9 @@ static void prodtest_optiga_id_read(cli_t* cli) {
optiga_get_data_object(OPTIGA_OID_COPROC_UID, false, optiga_id,
sizeof(optiga_id), &optiga_id_size);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_get_data_object error %d for 0x%04x.",
- ret, OPTIGA_OID_COPROC_UID);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_ID_READ,
+ "optiga_get_data_object error %d for 0x%04x.", ret,
+ OPTIGA_OID_COPROC_UID);
return;
}
@@ -330,8 +336,8 @@ static void cert_read(cli_t* cli, uint16_t oid) {
optiga_result ret =
optiga_get_data_object(oid, false, cert, sizeof(cert), &cert_size);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_get_data_object error %d for 0x%04x.",
- ret, oid);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_READ_GET,
+ "optiga_get_data_object error %d for 0x%04x.", ret, oid);
return;
}
@@ -364,7 +370,8 @@ static bool check_device_cert_chain(cli_t* cli, const uint8_t* chain,
size_t der_sig_size = 0;
if (optiga_calc_sign(OID_KEY_DEV, digest, sizeof(digest), &der_sig[2],
sizeof(der_sig) - 2, &der_sig_size) != OPTIGA_SUCCESS) {
- cli_error(cli, CLI_ERROR, "check_device_cert_chain, optiga_calc_sign.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_READ_SIGN,
+ "check_device_cert_chain, optiga_calc_sign.");
return false;
}
der_sig[1] = der_sig_size;
@@ -388,9 +395,11 @@ static void cert_write(cli_t* cli, uint16_t oid) {
if (!cli_arg_hex(cli, "hex-data", data_bytes, sizeof(data_bytes), &len)) {
if (len == sizeof(data_bytes)) {
- cli_error(cli, CLI_ERROR, "Certificate too long.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_WRITE_TOO_LONG,
+ "Certificate too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_WRITE_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
@@ -407,7 +416,8 @@ static void cert_write(cli_t* cli, uint16_t oid) {
optiga_result ret = optiga_set_data_object(oid, false, data_bytes, len);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_set_data error %d for 0x%04x.", ret, oid);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_WRITE_SET,
+ "optiga_set_data error %d for 0x%04x.", ret, oid);
return;
}
@@ -417,8 +427,8 @@ static void cert_write(cli_t* cli, uint16_t oid) {
ret = optiga_get_data_object(oid, false, cert, sizeof(cert), &cert_size);
if (OPTIGA_SUCCESS != ret || cert_size != len ||
memcmp(data_bytes, cert, len) != 0) {
- cli_error(cli, CLI_ERROR, "optiga_get_data_object error %d for 0x%04x.",
- ret, oid);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_CERT_WRITE_VERIFY,
+ "optiga_get_data_object error %d for 0x%04x.", ret, oid);
return;
}
@@ -456,7 +466,8 @@ static void pubkey_read(cli_t* cli, uint16_t oid,
optiga_calc_ssec(OPTIGA_CURVE_P256, oid, BASE_POINT, sizeof(BASE_POINT),
public_key_x, sizeof(public_key_x), &public_key_x_size);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_calc_ssec error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PUBKEY_CALC_SSEC,
+ "optiga_calc_ssec error %d.", ret);
return;
}
@@ -470,7 +481,8 @@ static void pubkey_read(cli_t* cli, uint16_t oid,
// for the y-coordinate here.
uint8_t masked_public_key[ECDSA_PUBLIC_KEY_COMPRESSED_SIZE] = {0x02};
if (public_key_x_size != sizeof(public_key_x)) {
- cli_error(cli, CLI_ERROR, "unexpected public key size");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PUBKEY_SIZE,
+ "unexpected public key size");
return;
}
memcpy(&masked_public_key[1], public_key_x, sizeof(public_key_x));
@@ -478,7 +490,7 @@ static void pubkey_read(cli_t* cli, uint16_t oid,
uint8_t unmasked_pub_key[ECDSA_PUBLIC_KEY_SIZE] = {0};
if (ecdsa_unmask_public_key(&nist256p1, masking_key, masked_public_key,
unmasked_pub_key) != 0) {
- cli_error(cli, CLI_ERROR, "key masking error");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_PUBKEY_MASK, "key masking error");
return;
}
memcpy(public_key_x, &unmasked_pub_key[1], sizeof(public_key_x));
@@ -510,9 +522,11 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
if (!cli_arg_hex(cli, "hex-data", data_bytes, sizeof(data_bytes), &len)) {
if (len == sizeof(data_bytes)) {
- cli_error(cli, CLI_ERROR, "Key too long.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_KEY_LONG,
+ "Key too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_HEX,
+ "Hexadecimal decoding error.");
}
return;
}
@@ -523,14 +537,16 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
}
if (len != EXPECTED_SIZE) {
- cli_error(cli, CLI_ERROR, "Unexpected input length.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_LEN,
+ "Unexpected input length.");
return;
}
// Expand sender's ephemeral public key.
uint8_t public_key[3 + 65] = {0x03, 0x42, 0x00};
if (ecdsa_uncompress_pubkey(&nist256p1, data_bytes, &public_key[3]) != 1) {
- cli_error(cli, CLI_ERROR, "Failed to decode public key.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_DECODE,
+ "Failed to decode public key.");
return;
}
@@ -542,7 +558,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
sizeof(secret), &secret_size);
if (OPTIGA_SUCCESS != ret) {
memzero(secret, sizeof(secret));
- cli_error(cli, CLI_ERROR, "optiga_calc_ssec error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_SSEC,
+ "optiga_calc_ssec error %d.", ret);
return;
}
@@ -551,7 +568,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
aes_decrypt_ctx ctx = {0};
AES_RETURN aes_ret = aes_decrypt_key256(secret, &ctx);
if (EXIT_SUCCESS != aes_ret) {
- cli_error(cli, CLI_ERROR, "aes_decrypt_key256 error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_KEY,
+ "aes_decrypt_key256 error.");
memzero(&ctx, sizeof(ctx));
memzero(secret, sizeof(secret));
return;
@@ -569,7 +587,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
memzero(secret, sizeof(secret));
if (EXIT_SUCCESS != aes_ret) {
memzero(fido_key, sizeof(fido_key));
- cli_error(cli, CLI_ERROR, "aes_cbc_decrypt error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_DEC,
+ "aes_cbc_decrypt error.");
return;
}
@@ -585,7 +604,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
ret = optiga_set_trust_anchor();
if (OPTIGA_SUCCESS != ret) {
memzero(fido_key, sizeof(fido_key));
- cli_error(cli, CLI_ERROR, "optiga_set_trust_anchor error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_ANCHOR,
+ "optiga_set_trust_anchor error %d.", ret);
return;
}
@@ -604,7 +624,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
if (secret_key_optiga_masking(masking_key) != sectrue ||
ecdsa_mask_scalar(&nist256p1, masking_key, fido_key, fido_key) != 0) {
memzero(fido_key, sizeof(fido_key));
- cli_error(cli, CLI_ERROR, "key masking error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_MASK,
+ "key masking error.");
return;
}
#endif // SECRET_KEY_MASKING
@@ -613,7 +634,8 @@ static void prodtest_optiga_keyfido_write(cli_t* cli) {
ret = optiga_set_priv_key(OID_KEY_FIDO, fido_key);
memzero(fido_key, sizeof(fido_key));
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_set_priv_key error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_PRIV,
+ "optiga_set_priv_key error %d.", ret);
return;
}
@@ -632,8 +654,9 @@ static void prodtest_optiga_counter_read(cli_t* cli) {
optiga_result ret =
optiga_get_data_object(OPTIGA_OID_SEC, false, &sec, sizeof(sec), &size);
if (OPTIGA_SUCCESS != ret || sizeof(sec) != size) {
- cli_error(cli, CLI_ERROR, "optiga_get_data_object error %d for 0x%04x.",
- ret, OPTIGA_OID_SEC);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_COUNTER_READ,
+ "optiga_get_data_object error %d for 0x%04x.", ret,
+ OPTIGA_OID_SEC);
return;
}
@@ -664,7 +687,8 @@ static void prodtest_optiga_keyfido_read(cli_t* cli) {
#ifdef SECRET_KEY_MASKING
uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE] = {0};
if (secret_key_optiga_masking(masking_key) != sectrue) {
- cli_error(cli, CLI_ERROR, "masking key not available");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_KEYFIDO_READ_MASK,
+ "masking key not available");
return;
}
pubkey_read(cli, OID_KEY_FIDO, masking_key);
@@ -918,10 +942,11 @@ static void prodtest_optiga_metadata_read(cli_t* cli) {
if (!cli_arg_hex(cli, "oid", oid_bytes, sizeof(oid_bytes), &oid_len)) {
if (oid_len == sizeof(oid_bytes)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_OPTIGA_META_READ_OID_LONG,
"OID too long. Four hexadecimal digits expected.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_OPTIGA_META_READ_HEX,
+ "Hexadecimal decoding error.");
}
return;
}
@@ -932,7 +957,7 @@ static void prodtest_optiga_metadata_read(cli_t* cli) {
}
if (oid_len != sizeof(oid_bytes)) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_OPTIGA_META_READ_OID_SHORT,
"OID too short. Four hexadecimal digits expected.");
return;
}
@@ -944,15 +969,16 @@ static void prodtest_optiga_metadata_read(cli_t* cli) {
optiga_result ret =
optiga_get_data_object(oid, true, serialized, sizeof(serialized), &size);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_get_metadata error %d for OID 0x%04x.",
- ret, oid);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_META_READ_GET,
+ "optiga_get_metadata error %d for OID 0x%04x.", ret, oid);
return;
}
optiga_metadata metadata = {0};
ret = optiga_parse_metadata(serialized, size, &metadata);
if (OPTIGA_SUCCESS != ret) {
- cli_error(cli, CLI_ERROR, "optiga_parse_metadata error %d.", ret);
+ cli_error(cli, PRODTEST_ERR_OPTIGA_META_READ_PARSE,
+ "optiga_parse_metadata error %d.", ret);
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c b/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
index 7a7f5314..4bd7d1f8 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
@@ -23,6 +23,8 @@
#include <rtl/cli.h>
#include <sys/flash_otp.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_otp_read(cli_t* cli, uint8_t block_num) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -34,14 +36,14 @@ static void prodtest_otp_read(cli_t* cli, uint8_t block_num) {
cli_trace(cli, "Reading device OTP memory...");
if (sectrue != flash_otp_read(block_num, 0, block, sizeof(block))) {
- cli_error(cli, CLI_ERROR, "Failed to read OTP memory.");
+ cli_error(cli, PRODTEST_ERR_OTP_READ, "Failed to read OTP memory.");
return;
}
char block_hex[FLASH_OTP_BLOCK_SIZE * 2 + 1];
if (!cstr_encode_hex(block_hex, sizeof(block_hex), block, sizeof(block))) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_OTP_HEX_ENCODE, "Buffer too small.");
return;
}
@@ -59,7 +61,7 @@ static void prodtest_otp_read(cli_t* cli, uint8_t block_num) {
if (strlen(block_text) > 0) {
cli_ok(cli, "%s", block_text);
} else {
- cli_error(cli, CLI_ERROR_NODATA, "OTP block is empty.");
+ cli_error(cli, PRODTEST_ERR_OTP_EMPTY, "OTP block is empty.");
}
}
@@ -106,12 +108,12 @@ static void prodtest_otp_write(cli_t* cli, uint8_t block_num) {
char block_hex[FLASH_OTP_BLOCK_SIZE * 2 + 1];
if (!cstr_encode_hex(block_hex, sizeof(block_hex), block, sizeof(block))) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_OTP_WRITE_HEX_ENCODE, "Buffer too small.");
return;
}
if (sectrue == flash_otp_is_locked(block_num)) {
- cli_error(cli, CLI_ERROR_LOCKED,
+ cli_error(cli, PRODTEST_ERR_OTP_LOCKED,
"OTP block is locked and cannot be written again.");
return;
}
@@ -121,7 +123,7 @@ static void prodtest_otp_write(cli_t* cli, uint8_t block_num) {
if (!dry_run) {
if (sectrue != flash_otp_write(block_num, 0, block, sizeof(block))) {
- cli_error(cli, CLI_ERROR, "Failed to write OTP block.");
+ cli_error(cli, PRODTEST_ERR_OTP_WRITE, "Failed to write OTP block.");
return;
}
}
@@ -130,7 +132,7 @@ static void prodtest_otp_write(cli_t* cli, uint8_t block_num) {
if (!dry_run) {
if (sectrue != flash_otp_lock(block_num)) {
- cli_error(cli, CLI_ERROR, "Failed to lock the OTP block.");
+ cli_error(cli, PRODTEST_ERR_OTP_LOCK, "Failed to lock the OTP block.");
return;
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
index 1477a407..0bd9da52 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
@@ -24,9 +24,10 @@
#include <rtl/cli.h>
#include <rtl/printf.h>
#include <sec/unit_properties.h>
+#include <stdlib.h>
#include <sys/flash_otp.h>
-#include <stdlib.h>
+#include "prodtest_error_codes.h"
#include "prodtest_optiga.h"
#ifdef USE_TROPIC
@@ -50,13 +51,15 @@ static void prodtest_otp_variant_read(cli_t* cli) {
if (sectrue !=
flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT, 0, block, sizeof(block))) {
- cli_error(cli, CLI_ERROR, "Failed to read OTP memory.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_BLOCK_READ,
+ "Failed to read OTP memory.");
return;
}
if (sectrue != flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT_REWORK, 0,
block_rework, sizeof(block_rework))) {
- cli_error(cli, CLI_ERROR, "Failed to read OTP memory.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_REWORK_BLOCK_READ,
+ "Failed to read OTP memory.");
return;
}
@@ -68,7 +71,7 @@ static void prodtest_otp_variant_read(cli_t* cli) {
char block_hex[FLASH_OTP_BLOCK_SIZE * 2 + 1];
if (!cstr_encode_hex(block_hex, sizeof(block_hex), block, sizeof(block))) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_HEX_ENCODE, "Buffer too small.");
return;
}
@@ -143,7 +146,8 @@ static void prodtest_otp_variant_write(cli_t* cli) {
#ifdef SECRET_LOCK_SLOT_OFFSET
if (sectrue != secret_is_locked()) {
- cli_error(cli, CLI_ERROR, "Secrets not locked");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_SECRETS_NOT_LOCKED,
+ "Secrets not locked");
return;
}
#endif
@@ -152,7 +156,8 @@ static void prodtest_otp_variant_write(cli_t* cli) {
optiga_locked_status optiga_status = get_optiga_locked_status(cli);
if (optiga_status == OPTIGA_LOCKED_FALSE) {
- cli_error(cli, CLI_ERROR, "Optiga not locked");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_OPTIGA_NOT_LOCKED,
+ "Optiga not locked");
return;
}
@@ -166,7 +171,8 @@ static void prodtest_otp_variant_write(cli_t* cli) {
tropic_locked_status tropic_status = get_tropic_locked_status(cli);
if (tropic_status == TROPIC_LOCKED_FALSE) {
- cli_error(cli, CLI_ERROR, "Tropic not locked");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_TROPIC_NOT_LOCKED,
+ "Tropic not locked");
return;
}
@@ -182,13 +188,13 @@ static void prodtest_otp_variant_write(cli_t* cli) {
block_num = FLASH_OTP_BLOCK_DEVICE_VARIANT_REWORK;
if (sectrue == flash_otp_is_locked(block_num)) {
- cli_error(cli, CLI_ERROR_LOCKED,
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_REWORK_LOCKED,
"OTP rework block is locked and cannot be written again.");
return;
}
if (sectrue != flash_otp_is_locked(FLASH_OTP_BLOCK_DEVICE_VARIANT)) {
- cli_error(cli, CLI_ERROR_LOCKED,
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_FIRST_NOT_LOCKED,
"Variant first block in not locked, rework not allowed.");
return;
}
@@ -196,24 +202,27 @@ static void prodtest_otp_variant_write(cli_t* cli) {
uint8_t block_read[FLASH_OTP_BLOCK_SIZE] = {0};
if (sectrue != flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT, 0, block_read,
sizeof(block_read))) {
- cli_error(cli, CLI_ERROR, "Failed to read OTP memory.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_REWORK_READ,
+ "Failed to read OTP memory.");
return;
}
if (memcmp(block_read, block, sizeof(block_read)) == 0) {
- cli_error(cli, CLI_ERROR, "Rework not needed, already up to date.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_REWORK_NOT_NEEDED,
+ "Rework not needed, already up to date.");
return;
}
}
if (sectrue == flash_otp_is_locked(block_num)) {
- cli_error(cli, CLI_ERROR_LOCKED,
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_LOCKED,
"OTP block is locked and cannot be written again.");
return;
}
char block_hex[FLASH_OTP_BLOCK_SIZE * 2 + 1];
if (!cstr_encode_hex(block_hex, sizeof(block_hex), block, sizeof(block))) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_WRITE_HEX_ENCODE,
+ "Buffer too small.");
return;
}
@@ -222,7 +231,8 @@ static void prodtest_otp_variant_write(cli_t* cli) {
if (!dry_run) {
if (sectrue != flash_otp_write(block_num, 0, block, sizeof(block))) {
- cli_error(cli, CLI_ERROR, "Failed to write OTP block.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_WRITE,
+ "Failed to write OTP block.");
return;
}
}
@@ -231,7 +241,8 @@ static void prodtest_otp_variant_write(cli_t* cli) {
if (!dry_run) {
if (sectrue != flash_otp_lock(block_num)) {
- cli_error(cli, CLI_ERROR, "Failed to lock the OTP block.");
+ cli_error(cli, PRODTEST_ERR_OTP_VARIANT_LOCK,
+ "Failed to lock the OTP block.");
return;
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_power_manager.c b/core/embed/projects/prodtest/cmd/prodtest_power_manager.c
index 826fc95f..da7426a1 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_power_manager.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_power_manager.c
@@ -34,6 +34,7 @@
#include <sys/systick.h>
#include "prodtest.h"
+#include "prodtest_error_codes.h"
void prodtest_pm_hibernate(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
@@ -48,12 +49,13 @@ void prodtest_pm_hibernate(cli_t* cli) {
status = pm_get_state(&state);
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get power manager state");
+ cli_error(cli, PRODTEST_ERR_PM_STATE_GET,
+ "Failed to get power manager state");
return;
}
if (!pm_hibernate()) {
- cli_error(cli, CLI_ERROR, "Failed to hibernate.");
+ cli_error(cli, PRODTEST_ERR_PM_HIBERNATE, "Failed to hibernate.");
return;
}
}
@@ -120,7 +122,8 @@ void prodtest_pm_charge_disable(cli_t* cli) {
pm_status_t status = pm_charging_disable();
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to enable battery charging");
+ cli_error(cli, PRODTEST_ERR_PM_CHARGE_DISABLE,
+ "Failed to enable battery charging");
return;
}
@@ -137,7 +140,8 @@ void prodtest_pm_charge_enable(cli_t* cli) {
pm_status_t status = pm_charging_enable();
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to enable battery charging");
+ cli_error(cli, PRODTEST_ERR_PM_CHARGE_ENABLE,
+ "Failed to enable battery charging");
return;
}
@@ -156,7 +160,8 @@ void prodtest_pm_fuel_gauge_monitor(cli_t* cli) {
pm_report_t report;
pm_status_t status = pm_get_report(&report);
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get power manager report");
+ cli_error(cli, PRODTEST_ERR_PM_FUEL_GAUGE_REPORT_GET,
+ "Failed to get power manager report");
return;
}
@@ -202,7 +207,8 @@ void prodtest_pm_report(cli_t* cli) {
pm_report_t report;
pm_status_t status = pm_get_report(&report);
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get power manager report");
+ cli_error(cli, PRODTEST_ERR_PM_REPORT_GET,
+ "Failed to get power manager report");
return;
}
cli_trace(cli, "Power manager report:");
@@ -302,7 +308,8 @@ void prodtest_pm_event_monitor(cli_t* cli) {
}
if (!pm_get_events(&event_flag)) {
- cli_error(cli, CLI_ERROR, "Failed to get power manager events");
+ cli_error(cli, PRODTEST_ERR_PM_EVENTS_GET,
+ "Failed to get power manager events");
continue;
}
@@ -376,7 +383,7 @@ void prodtest_pm_new_soc_estimate(cli_t* cli) {
backup_ram_erase_item(BACKUP_RAM_KEY_PM_RECOVERY);
reboot_device();
- cli_error(cli, CLI_ERROR, "failed to reboot");
+ cli_error(cli, PRODTEST_ERR_PM_REBOOT, "failed to reboot");
}
void prodtest_pm_battery_test(cli_t* cli) {
@@ -410,14 +417,15 @@ void prodtest_pm_battery_test(cli_t* cli) {
*/
for (uint8_t i = 0; i < tested_samples; i++) {
if (cli_aborted(cli)) {
- cli_error(cli, CLI_ERROR, "Aborted.");
+ cli_error(cli, PRODTEST_ERR_PM_BATTERY_TEST_ABORTED, "Aborted.");
goto cleanup;
}
pm_report_t report;
pm_status_t status = pm_get_report(&report);
if (status != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get power manager report.");
+ cli_error(cli, PRODTEST_ERR_PM_BATTERY_TEST_REPORT_GET,
+ "Failed to get power manager report.");
goto cleanup;
}
@@ -441,7 +449,7 @@ void prodtest_pm_battery_test(cli_t* cli) {
if (passed) {
cli_ok(cli, "Battery test passed.");
} else {
- cli_error(cli, CLI_ERROR, "Battery test failed.");
+ cli_error(cli, PRODTEST_ERR_PM_BATTERY_TEST, "Battery test failed.");
}
cleanup:
diff --git a/core/embed/projects/prodtest/cmd/prodtest_prodtest.c b/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
index b55d9aea..5c6acda7 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_prodtest.c
@@ -24,6 +24,8 @@
#include <rtl/cli.h>
#include <sec/fwutils.h>
+#include "prodtest_error_codes.h"
+
#ifdef USE_BLE
#include "prodtest_ble.h"
#endif
@@ -64,7 +66,8 @@ static void prodtest_prodtest_wipe(cli_t* cli) {
#if defined(USE_BLE) && !defined(TREZOR_EMULATOR)
cli_trace(cli, "Erasing BLE bonds...");
if (!prodtest_ble_erase_bonds(cli)) {
- cli_error(cli, CLI_ERROR, "Failed to erase BLE bonds.");
+ cli_error(cli, PRODTEST_ERR_PRODTEST_WIPE_BLE_BONDS_ERASE,
+ "Failed to erase BLE bonds.");
return;
}
#endif
diff --git a/core/embed/projects/prodtest/cmd/prodtest_rtc.c b/core/embed/projects/prodtest/cmd/prodtest_rtc.c
index 41d08189..4edfbd5c 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_rtc.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_rtc.c
@@ -24,6 +24,8 @@
#include <rtl/cli.h>
#include <sys/rtc.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_rtc_timestamp(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -32,7 +34,8 @@ static void prodtest_rtc_timestamp(cli_t* cli) {
uint32_t timestamp;
if (!rtc_get_timestamp(×tamp)) {
- cli_error(cli, CLI_ERROR, "Failed to get RTC timestamp");
+ cli_error(cli, PRODTEST_ERR_RTC_TIMESTAMP_GET,
+ "Failed to get RTC timestamp");
return;
}
cli_ok(cli, "%u", timestamp);
@@ -56,7 +59,7 @@ static void prodtest_rtc_set(cli_t* cli) {
}
if (!rtc_set(year, month, day, hour, minute, second)) {
- cli_error(cli, CLI_ERROR, "Failed to set RTC time");
+ cli_error(cli, PRODTEST_ERR_RTC_TIME_SET, "Failed to set RTC time");
return;
}
cli_ok(cli, "");
@@ -70,7 +73,7 @@ static void prodtest_rtc_get(cli_t* cli) {
rtc_datetime_t datetime;
if (!rtc_get(&datetime)) {
- cli_error(cli, CLI_ERROR, "Failed to get RTC time");
+ cli_error(cli, PRODTEST_ERR_RTC_TIME_GET, "Failed to get RTC time");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_sdcard.c b/core/embed/projects/prodtest/cmd/prodtest_sdcard.c
index 51aae617..19379f4e 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_sdcard.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_sdcard.c
@@ -25,6 +25,8 @@
#include <rtl/cli.h>
#include <sys/systick.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_sdcard_test(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -40,7 +42,7 @@ static void prodtest_sdcard_test(cli_t* cli) {
#ifndef TREZOR_MODEL_T3T1
if (sectrue != sdcard_is_present()) {
cli_trace(cli, "The inserted SD card is required.");
- cli_error(cli, "no-card", "");
+ cli_error(cli, PRODTEST_ERR_SDCARD_NO_CARD, "");
return;
}
#else
@@ -50,14 +52,16 @@ static void prodtest_sdcard_test(cli_t* cli) {
cli_trace(cli, "Powering on the SD card...");
if (sectrue != sdcard_power_on_unchecked(low_speed)) {
- cli_error(cli, CLI_ERROR, "SD card power on sequence failed.");
+ cli_error(cli, PRODTEST_ERR_SDCARD_POWER_ON,
+ "SD card power on sequence failed.");
return;
}
cli_trace(cli, "Reading data from the SD card...");
if (sectrue != sdcard_read_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) {
- cli_error(cli, CLI_ERROR, "Failed to read data from SD card.");
+ cli_error(cli, PRODTEST_ERR_SDCARD_READ_INITIAL,
+ "Failed to read data from SD card.");
goto power_off;
}
@@ -70,7 +74,8 @@ static void prodtest_sdcard_test(cli_t* cli) {
if (sectrue !=
sdcard_write_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) {
- cli_error(cli, CLI_ERROR, "Failed to write data from the SD card.");
+ cli_error(cli, PRODTEST_ERR_SDCARD_WRITE,
+ "Failed to write data from the SD card.");
goto power_off;
}
@@ -78,12 +83,14 @@ static void prodtest_sdcard_test(cli_t* cli) {
if (sectrue !=
sdcard_read_blocks(buf2, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) {
- cli_error(cli, CLI_ERROR, "Failed to read data from SD card.");
+ cli_error(cli, PRODTEST_ERR_SDCARD_READ_VERIFY,
+ "Failed to read data from SD card.");
goto power_off;
}
if (0 != memcmp(buf1, buf2, sizeof(buf1))) {
- cli_error(cli, CLI_ERROR, "Data mismatch after writing to SD card.");
+ cli_error(cli, PRODTEST_ERR_SDCARD_DATA_MISMATCH,
+ "Data mismatch after writing to SD card.");
goto power_off;
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_secrets.c b/core/embed/projects/prodtest/cmd/prodtest_secrets.c
index ac7007e2..76b128c2 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_secrets.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_secrets.c
@@ -99,7 +99,8 @@ static void prodtest_secrets_init(cli_t* cli) {
// Make sure that the secrets sector isn't locked so that we don't overwrite
// the MCU's nRF pairing secret.
if (secfalse != secret_is_locked()) {
- cli_error(cli, CLI_ERROR, "Secret sector is already locked");
+ cli_error(cli, PRODTEST_ERR_SECRETS_SECTOR_ALREADY_LOCKED,
+ "Secret sector is already locked");
return;
}
#endif
@@ -110,7 +111,8 @@ static void prodtest_secrets_init(cli_t* cli) {
optiga_locked_status optiga_status = get_optiga_locked_status(cli);
if (optiga_status == OPTIGA_LOCKED_TRUE) {
- cli_error(cli, CLI_ERROR, "Optiga is already locked");
+ cli_error(cli, PRODTEST_ERR_SECRETS_OPTIGA_ALREADY_LOCKED,
+ "Optiga is already locked");
return;
}
@@ -125,7 +127,8 @@ static void prodtest_secrets_init(cli_t* cli) {
// MCU's pairing secrets.
curve25519_key tropic_public = {0};
if (secret_key_tropic_public(tropic_public) == sectrue) {
- cli_error(cli, CLI_ERROR, "Tropic pairing has already started.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_TROPIC_PAIRING_STARTED,
+ "Tropic pairing has already started.");
return;
}
@@ -134,7 +137,8 @@ static void prodtest_secrets_init(cli_t* cli) {
// provisioning the factory pairing key should still be valid.
if (tropic_custom_session_start(cli, TROPIC_FACTORY_PAIRING_KEY_SLOT) !=
LT_OK) {
- cli_error(cli, CLI_ERROR, "`tropic_custom_session_start()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_TROPIC_SESSION,
+ "`tropic_custom_session_start()` failed.");
return;
}
#endif
@@ -142,7 +146,7 @@ static void prodtest_secrets_init(cli_t* cli) {
#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
if (set_random_secret(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
SECRET_MASTER_KEY_SLOT_SIZE) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_SECRETS_MASTER_KEY_PRIV,
"`set_random_secret` failed for privileged master key.");
return;
}
@@ -151,7 +155,7 @@ static void prodtest_secrets_init(cli_t* cli) {
#ifdef SECRET_UNPRIVILEGED_MASTER_KEY_SLOT
if (set_random_secret(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
SECRET_MASTER_KEY_SLOT_SIZE) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_SECRETS_MASTER_KEY_UNPRIV,
"`set_random_secret` failed for unprivileged master key.");
return;
}
@@ -161,7 +165,7 @@ static void prodtest_secrets_init(cli_t* cli) {
#ifdef SECRET_OPTIGA_SLOT
if (set_random_secret(SECRET_OPTIGA_SLOT, OPTIGA_PAIRING_SECRET_SIZE) !=
sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_SECRETS_OPTIGA_PAIRING,
"`set_random_secret` failed for optiga pairing secret.");
return;
}
@@ -180,14 +184,16 @@ static void prodtest_secrets_get_mcu_device_key(cli_t* cli) {
uint8_t seed[MLDSA_SEEDBYTES] = {0};
if (secret_key_mcu_device_auth(seed) != sectrue) {
- cli_error(cli, CLI_ERROR, "`secret_key_mcu_device_auth()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_DEVICE_KEY_AUTH,
+ "`secret_key_mcu_device_auth()` failed.");
goto cleanup;
}
uint8_t mcu_public[MCU_ATTESTATION_PUBKEY_SIZE] = {0};
uint8_t mcu_private[MCU_ATTESTATION_PRIVKEY_SIZE] = {0};
if (mldsa_keypair_internal(mcu_public, mcu_private, seed) != 0) {
- cli_error(cli, CLI_ERROR, "`mldsa_keypair_internal()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_DEVICE_KEY_KEYPAIR,
+ "`mldsa_keypair_internal()` failed.");
goto cleanup;
}
@@ -195,7 +201,8 @@ static void prodtest_secrets_get_mcu_device_key(cli_t* cli) {
if (!secure_channel_encrypt(mcu_public, sizeof(mcu_public), NULL, 0,
output)) {
// `secure_channel_handshake_2()` might not have been called
- cli_error(cli, CLI_ERROR, "`secure_channel_encrypt()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_DEVICE_KEY_ENCRYPT,
+ "`secure_channel_encrypt()` failed.");
goto cleanup;
}
@@ -213,14 +220,16 @@ static bool check_device_cert_chain(cli_t* cli, const uint8_t* chain,
uint8_t seed[MLDSA_SEEDBYTES] = {0};
if (secret_key_mcu_device_auth(seed) != sectrue) {
- cli_error(cli, CLI_ERROR, "`secret_key_mcu_device_auth()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERT_CHAIN_AUTH,
+ "`secret_key_mcu_device_auth()` failed.");
goto cleanup;
}
uint8_t mcu_public[MCU_ATTESTATION_PUBKEY_SIZE] = {0};
uint8_t mcu_private[MCU_ATTESTATION_PRIVKEY_SIZE] = {0};
if (mldsa_keypair_internal(mcu_public, mcu_private, seed) != 0) {
- cli_error(cli, CLI_ERROR, "`mldsa_keypair_internal()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERT_CHAIN_KEYPAIR,
+ "`mldsa_keypair_internal()` failed.");
goto cleanup;
}
@@ -236,7 +245,8 @@ static bool check_device_cert_chain(cli_t* cli, const uint8_t* chain,
ENCODED_EMPTY_CONTEXT_STRING,
sizeof(ENCODED_EMPTY_CONTEXT_STRING), rnd,
mcu_private, 0) != 0) {
- cli_error(cli, CLI_ERROR, "`mldsa_signature_internal()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_SIGN_SIGNATURE,
+ "`mldsa_signature_internal()` failed.");
goto cleanup;
}
@@ -262,16 +272,19 @@ static void prodtest_secrets_certdev_write(cli_t* cli) {
}
#ifdef TREZOR_EMULATOR
- cli_error(cli, CLI_ERROR, "Not implemented");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERTDEV_WRITE_NOT_IMPL,
+ "Not implemented");
#else
size_t certificate_length = 0;
uint8_t certificate[MCU_ATTESTATION_MAX_CERT_SIZE] = {0};
if (!cli_arg_hex(cli, "hex-data", certificate, sizeof(certificate),
&certificate_length)) {
if (certificate_length == sizeof(certificate)) {
- cli_error(cli, CLI_ERROR, "Certificate too long.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERT_TOO_LONG,
+ "Certificate too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERT_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
@@ -283,7 +296,8 @@ static void prodtest_secrets_certdev_write(cli_t* cli) {
if (secret_mcu_device_cert_write(certificate, certificate_length) !=
sectrue) {
- cli_error(cli, CLI_ERROR, "secret_mcu_device_cert_write() failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_WRITE,
+ "secret_mcu_device_cert_write() failed.");
return;
}
@@ -298,14 +312,15 @@ static void prodtest_secrets_certdev_read(cli_t* cli) {
}
#ifdef TREZOR_EMULATOR
- cli_error(cli, CLI_ERROR, "Not implemented");
+ cli_error(cli, PRODTEST_ERR_SECRETS_CERTDEV_READ_NOT_IMPL, "Not implemented");
#else
uint8_t certificate[MCU_ATTESTATION_MAX_CERT_SIZE] = {0};
size_t certificate_length = 0;
if (secret_mcu_device_cert_read(certificate, sizeof(certificate),
&certificate_length) != sectrue) {
- cli_error(cli, CLI_ERROR, "secret_mcu_device_cert_read() failed.");
+ cli_error(cli, PRODTEST_ERR_SECRETS_READ,
+ "secret_mcu_device_cert_read() failed.");
return;
}
@@ -328,7 +343,8 @@ static void prodtest_secrets_lock(cli_t* cli) {
}
if (sectrue != secret_lock()) {
- cli_error(cli, CLI_ERROR, "Failed to lock secret sector");
+ cli_error(cli, PRODTEST_ERR_SECRETS_SECTOR_LOCK,
+ "Failed to lock secret sector");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_secure_channel.c b/core/embed/projects/prodtest/cmd/prodtest_secure_channel.c
index b24dc32b..51cc8262 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_secure_channel.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_secure_channel.c
@@ -19,6 +19,7 @@
#include <rtl/cli.h>
+#include "prodtest_error_codes.h"
#include "secure_channel.h"
static void prodtest_secure_channel_handshake_1(cli_t* cli) {
@@ -30,7 +31,8 @@ static void prodtest_secure_channel_handshake_1(cli_t* cli) {
uint8_t output[SECURE_CHANNEL_OUTPUT_SIZE] = {0};
if (!secure_channel_handshake_1(output)) {
- cli_error(cli, CLI_ERROR, "`secure_channel_handshake_1()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_INIT,
+ "`secure_channel_handshake_1()` failed.");
return;
}
@@ -47,21 +49,25 @@ static void prodtest_secure_channel_handshake_2(cli_t* cli) {
size_t input_length = 0;
if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
if (input_length == sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Input too long.");
+ cli_error(cli, PRODTEST_ERR_SECURE_CHANNEL_INPUT_TOO_LONG,
+ "Input too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_SECURE_CHANNEL_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
if (input_length != SECURE_CHANNEL_INPUT_SIZE) {
- cli_error(cli, CLI_ERROR, "Unexpected input length. Expecting %d bytes.",
+ cli_error(cli, PRODTEST_ERR_SECURE_CHANNEL_INPUT_LEN,
+ "Unexpected input length. Expecting %d bytes.",
(int)SECURE_CHANNEL_INPUT_SIZE);
}
if (!secure_channel_handshake_2(input)) {
// Either `secure_channel_handshake_1()` has not been called or the keys do
// not match.
- cli_error(cli, CLI_ERROR, "`secure_channel_handshake_2()` failed.");
+ cli_error(cli, PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_FINISH,
+ "`secure_channel_handshake_2()` failed.");
}
cli_ok(cli, "");
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tamper.c b/core/embed/projects/prodtest/cmd/prodtest_tamper.c
index 107e8bae..11ee5a09 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_tamper.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_tamper.c
@@ -24,6 +24,8 @@
#include <rtl/cli.h>
#include <sec/tamper.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_tamper_read(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -33,7 +35,8 @@ static void prodtest_tamper_read(cli_t* cli) {
bool init_ok = tamper_init();
if (!init_ok) {
- cli_error(cli, CLI_ERROR, "Cannot initialize tamper driver.");
+ cli_error(cli, PRODTEST_ERR_TAMPER_INIT,
+ "Cannot initialize tamper driver.");
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_telemetry.c b/core/embed/projects/prodtest/cmd/prodtest_telemetry.c
index e955c5bb..85859706 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_telemetry.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_telemetry.c
@@ -25,6 +25,8 @@
#include <sec/telemetry.h>
#include <sec/unit_properties.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_telemetry(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -34,7 +36,8 @@ static void prodtest_telemetry(cli_t* cli) {
telemetry_data_t data;
if (!telemetry_get(&data)) {
- cli_error(cli, CLI_ERROR_NODATA, "Telemetry data not available");
+ cli_error(cli, PRODTEST_ERR_TELEMETRY_NOT_AVAILABLE,
+ "Telemetry data not available");
return;
}
@@ -56,7 +59,8 @@ static void prodtest_telemetry_reset(cli_t* cli) {
unit_properties_t props = {0};
unit_properties_get(&props);
if (props.locked) {
- cli_error(cli, CLI_ERROR, "Device is not in manufacturing mode.");
+ cli_error(cli, PRODTEST_ERR_TELEMETRY_NOT_MANUFACTURING,
+ "Device is not in manufacturing mode.");
return;
}
#endif
diff --git a/core/embed/projects/prodtest/cmd/prodtest_touch.c b/core/embed/projects/prodtest/cmd/prodtest_touch.c
index cbd90f7c..3fe6fce8 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_touch.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_touch.c
@@ -27,12 +27,15 @@
#include <rtl/cli.h>
#include <sys/systick.h>
+#include "prodtest_error_codes.h"
+
#include "../prodtest.h"
static bool ensure_touch_init(cli_t* cli) {
cli_trace(cli, "Initializing the touch controller...");
if (sectrue != touch_init()) {
- cli_error(cli, CLI_ERROR, "Cannot initialize touch controller.");
+ cli_error(cli, PRODTEST_ERR_TOUCH_INIT,
+ "Cannot initialize touch controller.");
return false;
}
return true;
@@ -128,7 +131,7 @@ static void prodtest_touch_test(cli_t* cli) {
cli_ok(cli, "%d %d", x, y);
} else {
if (!cli_aborted(cli)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_TOUCH_QUADRANT_TIMEOUT, "Timeout");
}
}
@@ -187,7 +190,7 @@ static void prodtest_touch_test_custom(cli_t* cli) {
while (true) {
if (ticks_expired(expire_time)) {
- cli_error(cli, CLI_ERROR_TIMEOUT, "");
+ cli_error(cli, PRODTEST_ERR_TOUCH_CUSTOM_TIMEOUT, "Timeout");
break;
}
@@ -252,7 +255,8 @@ static void prodtest_touch_test_idle(cli_t* cli) {
}
if (activity) {
- cli_error(cli, CLI_ERROR, "Unexpected activity detected.");
+ cli_error(cli, PRODTEST_ERR_TOUCH_UNEXPECTED_ACTIVITY,
+ "Unexpected activity detected.");
goto cleanup;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tropic.c b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
index 113a150c..d5a1d22f 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_tropic.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
@@ -489,7 +489,7 @@ static void prodtest_tropic_get_riscv_fw_version(cli_t* cli) {
uint8_t version[TR01_L2_GET_INFO_RISCV_FW_SIZE] = {0};
lt_ret_t ret = lt_get_info_riscv_fw_ver(tropic_handle, version);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_RISCV_FW_VERSION,
"lt_get_info_riscv_fw_ver() failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -510,7 +510,7 @@ static void prodtest_tropic_get_spect_fw_version(cli_t* cli) {
uint8_t version[TR01_L2_GET_INFO_SPECT_FW_SIZE];
lt_ret_t ret = lt_get_info_spect_fw_ver(tropic_handle, version);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_SPECT_FW_VERSION,
"lt_get_info_spect_fw_ver() failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -531,7 +531,8 @@ static void prodtest_tropic_get_chip_id(cli_t* cli) {
struct lt_chip_id_t chip_id;
lt_ret_t ret = lt_get_info_chip_id(tropic_handle, &chip_id);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "lt_get_info_chip_id() failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_CHIP_ID,
+ "lt_get_info_chip_id() failed with error '%s'",
lt_ret_verbose(ret));
return;
}
@@ -554,7 +555,8 @@ static void prodtest_tropic_certtropic_read(cli_t* cli) {
size_t tropic_cert_chain_length = 0;
if (!tropic_get_cert_chain_ptr(cli, &tropic_cert_chain,
&tropic_cert_chain_length)) {
- cli_error(cli, CLI_ERROR, "`tropic_get_cert_chain_ptr()` failed");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_READ,
+ "`tropic_get_cert_chain_ptr()` failed");
return;
}
@@ -603,7 +605,7 @@ tropic_locked_status get_tropic_locked_status(cli_t* cli) {
"midway.");
return TROPIC_LOCKED_FALSE;
} else {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_CHECK_SESSION,
"`tropic_custom_session_start()` failed with error '%s'",
lt_ret_verbose(ret));
return TROPIC_LOCKED_ERROR;
@@ -614,7 +616,7 @@ tropic_locked_status get_tropic_locked_status(cli_t* cli) {
ret = lt_read_whole_R_config(tropic_handle, &configuration_read);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_CHECK_R_CONFIG_READ,
"`lt_read_whole_R_config()` failed with error '%s'",
lt_ret_verbose(ret));
return TROPIC_LOCKED_ERROR;
@@ -630,7 +632,7 @@ tropic_locked_status get_tropic_locked_status(cli_t* cli) {
ret = lt_read_whole_I_config(tropic_handle, &configuration_read);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_CHECK_I_CONFIG_READ,
"`lt_read_whole_I_config()` failed with error '%s'",
lt_ret_verbose(ret));
return TROPIC_LOCKED_ERROR;
@@ -767,7 +769,7 @@ static void prodtest_tropic_pair(cli_t* cli) {
// MCU's flash before completing secrets-init, we would run into a deadlock.
curve25519_key unprivileged_private = {0};
if (secret_key_tropic_pairing_unprivileged(unprivileged_private) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_PUBKEY_UNPRIV,
"`secret_key_tropic_pairing_unprivileged()` failed.");
goto cleanup;
}
@@ -777,7 +779,7 @@ static void prodtest_tropic_pair(cli_t* cli) {
// Retrieve the privileged pairing key pair.
curve25519_key privileged_private = {0};
if (secret_key_tropic_pairing_privileged(privileged_private) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_PUBKEY_PRIV,
"`secret_key_tropic_pairing_privileged()` failed.");
goto cleanup;
}
@@ -787,7 +789,8 @@ static void prodtest_tropic_pair(cli_t* cli) {
// Get the Tropic01 public pairing key from the chip's certificate.
curve25519_key tropic_public = {0};
if (!tropic_get_pubkey(cli, tropic_public)) {
- cli_error(cli, CLI_ERROR, "`tropic_get_tropic_pubkey()` failed");
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_GET_PUBKEY,
+ "`tropic_get_tropic_pubkey()` failed");
goto cleanup;
}
@@ -799,18 +802,19 @@ static void prodtest_tropic_pair(cli_t* cli) {
// This is skipped in the prodtest emulator.
if (secret_key_set(SECRET_TROPIC_TROPIC_PUBKEY_SLOT, tropic_public,
sizeof(curve25519_key)) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_STORE_SET,
"`secret_key_set()` failed for tropic public key.");
goto cleanup;
}
#endif
if (secret_key_tropic_public(tropic_public_flash) != sectrue) {
- cli_error(cli, CLI_ERROR, "`secret_key_tropic_public()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_STORE_SK,
+ "`secret_key_tropic_public()` failed.");
goto cleanup;
}
}
if (memcmp(tropic_public, tropic_public_flash, sizeof(curve25519_key)) != 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_STORE_MISMATCH,
"Tropic public key does not match the expected value.");
goto cleanup;
}
@@ -825,7 +829,7 @@ static void prodtest_tropic_pair(cli_t* cli) {
// If the pairing key has already been written, `pairing_key_write()`
// returns `LT_OK`.
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_PRIV,
"`pairing_key_write()` failed for privileged pairing key with "
"error '%s'",
lt_ret_verbose(ret));
@@ -841,7 +845,7 @@ static void prodtest_tropic_pair(cli_t* cli) {
// returns `LT_OK`.
if (ret != LT_OK) {
cli_error(
- cli, CLI_ERROR,
+ cli, PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_UNPRIV,
"`pairing_key_write()` failed for unprivileged pairing key with "
"error '%s'",
lt_ret_verbose(ret));
@@ -854,7 +858,7 @@ static void prodtest_tropic_pair(cli_t* cli) {
// If the factory has already been invalidated,
// `lt_pairing_key_invalidate()` returns `LT_OK`.
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_CERT_SIGN,
"`lt_pairing_key_invalidate()` failed for factory pairing key "
"with error '%s'",
lt_ret_verbose(ret));
@@ -863,7 +867,8 @@ static void prodtest_tropic_pair(cli_t* cli) {
}
if (!tropic_is_paired(cli)) {
- cli_error(cli, CLI_ERROR, "`tropic_is_paired()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_PAIR_IS_PAIRED_FAILED,
+ "`tropic_is_paired()` failed.");
goto cleanup;
}
@@ -885,14 +890,15 @@ static void prodtest_tropic_get_access_credential(cli_t* cli) {
curve25519_key unprivileged_private = {0};
if (secret_key_tropic_pairing_unprivileged(unprivileged_private) != sectrue) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_ACCESS_CRED_PUBKEY,
"`secret_key_tropic_pairing_unprivileged()` failed.");
goto cleanup;
}
curve25519_key tropic_public = {0};
if (!tropic_get_pubkey(cli, tropic_public)) {
- cli_error(cli, CLI_ERROR, "`tropic_get_tropic_pubkey()` failed");
+ cli_error(cli, PRODTEST_ERR_TROPIC_ACCESS_CRED_GET_PUBKEY,
+ "`tropic_get_tropic_pubkey()` failed");
goto cleanup;
}
@@ -901,7 +907,8 @@ static void prodtest_tropic_get_access_credential(cli_t* cli) {
sizeof(unprivileged_private), tropic_public,
sizeof(curve25519_key), output)) {
// `secure_channel_handshake_2()` might not have been called
- cli_error(cli, CLI_ERROR, "`secure_channel_encrypt()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_ACCESS_CRED_ENCRYPT,
+ "`secure_channel_encrypt()` failed.");
goto cleanup;
}
@@ -919,7 +926,8 @@ static void prodtest_tropic_get_fido_masking_key(cli_t* cli) {
uint8_t fido_masking_key[ECDSA_PRIVATE_KEY_SIZE] = {0};
if (!secret_key_tropic_masking(fido_masking_key)) {
- cli_error(cli, CLI_ERROR, "`secret_key_tropic_masking()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_FIDO_KEY_MASKING,
+ "`secret_key_tropic_masking()` failed.");
goto cleanup;
}
@@ -927,7 +935,8 @@ static void prodtest_tropic_get_fido_masking_key(cli_t* cli) {
if (!secure_channel_encrypt(fido_masking_key, sizeof(fido_masking_key), NULL,
0, output)) {
// `secure_channel_handshake_2()` might not have been called
- cli_error(cli, CLI_ERROR, "`secure_channel_encrypt()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_FIDO_KEY_ENCRYPT,
+ "`secure_channel_encrypt()` failed.");
goto cleanup;
}
@@ -986,7 +995,8 @@ static void prodtest_tropic_handshake(cli_t* cli) {
}
if (!tropic_is_paired(cli)) {
- cli_error(cli, CLI_ERROR, "`tropic-pair` must be called first.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_NOT_PAIRED,
+ "`tropic-pair` must be called first.");
return;
}
@@ -994,14 +1004,17 @@ static void prodtest_tropic_handshake(cli_t* cli) {
size_t input_length = 0;
if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
if (input_length == sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Input too long.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LONG,
+ "Input too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
if (input_length != sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Unexpected input length. Expecting %d bytes.",
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LEN,
+ "Unexpected input length. Expecting %d bytes.",
(int)sizeof(input));
return;
}
@@ -1012,13 +1025,14 @@ static void prodtest_tropic_handshake(cli_t* cli) {
size_t request_length = 0;
ret = l2_get_req_len(input, sizeof(input), &request_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`get_req_len()` failed with error '%s'.",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_LEN,
+ "`get_req_len()` failed with error '%s'.", lt_ret_verbose(ret));
return;
}
if (input_length != request_length) {
- cli_error(cli, CLI_ERROR, "Request was damaged or truncated.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_DAMAGED,
+ "Request was damaged or truncated.");
return;
}
@@ -1026,7 +1040,7 @@ static void prodtest_tropic_handshake(cli_t* cli) {
ret = tropic_session_invalidate();
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_SEND,
"`tropic_session_invalidate()` failed with error '%s'.",
lt_ret_verbose(ret));
return;
@@ -1034,29 +1048,29 @@ static void prodtest_tropic_handshake(cli_t* cli) {
ret = lt_l2_send(&l2_state);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_l2_send()` failed with error '%s'.",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_L2_SEND,
+ "`lt_l2_send()` failed with error '%s'.", lt_ret_verbose(ret));
return;
}
ret = lt_l2_receive(&l2_state);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_l2_receive()` failed with error '%s'.",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_L2_RECEIVE,
+ "`lt_l2_receive()` failed with error '%s'.", lt_ret_verbose(ret));
return;
}
size_t response_length = 0;
ret = l2_get_rsp_len(l2_state.buff, sizeof(l2_state.buff), &response_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`get_rsp_len()` failed with error '%s'.",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_LEN,
+ "`get_rsp_len()` failed with error '%s'.", lt_ret_verbose(ret));
return;
}
if (response_length !=
51) { // 51 is the expected size of the handshake response
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_DAMAGED,
"Unexpected response length. Expecting 51 bytes, got %d bytes.",
(int)response_length);
return;
@@ -1098,15 +1112,17 @@ static void prodtest_tropic_send_command(cli_t* cli) {
size_t input_length = 0;
if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
if (input_length == sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Input too long.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_INPUT_LONG, "Input too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
if (g_tropic_handshake_state != TROPIC_HANDSHAKE_STATE_1) {
- cli_error(cli, CLI_ERROR, "You have to call `tropic-handshake` first.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_NO_HANDSHAKE,
+ "You have to call `tropic-handshake` first.");
return;
}
@@ -1116,19 +1132,21 @@ static void prodtest_tropic_send_command(cli_t* cli) {
size_t command_length = 0;
ret = l3_get_frame_len(input, sizeof(input), &command_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`l3_get_cmd_len()` failed with error '%s'.",
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_L3_LEN_REQ,
+ "`l3_get_cmd_len()` failed with error '%s'.",
lt_ret_verbose(ret));
return;
}
if (input_length != command_length) {
- cli_error(cli, CLI_ERROR, "Request was damaged or truncated.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_REQ_DAMAGED,
+ "Request was damaged or truncated.");
return;
}
ret = lt_l2_send_encrypted_cmd(&l2_state, (uint8_t*)input, input_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_SEND,
"`lt_l2_send_encrypted_cmd()` failed with error '%s'.",
lt_ret_verbose(ret));
return;
@@ -1137,7 +1155,7 @@ static void prodtest_tropic_send_command(cli_t* cli) {
uint8_t output[TR01_L2_MAX_FRAME_SIZE] = {0};
ret = lt_l2_recv_encrypted_res(&l2_state, output, sizeof(output));
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_RECEIVE,
"`lt_l2_recv_encrypted_res()` failed with error '%s'.",
lt_ret_verbose(ret));
return;
@@ -1146,7 +1164,8 @@ static void prodtest_tropic_send_command(cli_t* cli) {
size_t output_length = 0;
ret = l3_get_frame_len(output, sizeof(output), &output_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`l3_get_cmd_len()` failed with error '%s'.",
+ cli_error(cli, PRODTEST_ERR_TROPIC_CMD_L3_LEN_RSP,
+ "`l3_get_cmd_len()` failed with error '%s'.",
lt_ret_verbose(ret));
return;
}
@@ -1168,7 +1187,8 @@ static void prodtest_tropic_lock(cli_t* cli) {
}
if (!tropic_is_paired(cli)) {
- cli_error(cli, CLI_ERROR, "`tropic-pair` must be called first.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_NOT_PAIRED,
+ "`tropic-pair` must be called first.");
return;
}
@@ -1177,7 +1197,7 @@ static void prodtest_tropic_lock(cli_t* cli) {
ret = tropic_custom_session_start(cli, TROPIC_PRIVILEGED_PAIRING_KEY_SLOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_INIT,
"`tropic_custom_session_start()` for privileged key failed with "
"error '%s'",
lt_ret_verbose(ret));
@@ -1189,14 +1209,15 @@ static void prodtest_tropic_lock(cli_t* cli) {
ret = lt_r_config_erase(tropic_handle);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_r_config_erase()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_ERASE,
+ "`lt_r_config_erase()` failed with error '%s'",
lt_ret_verbose(ret));
return;
}
ret = lt_write_whole_R_config(tropic_handle, &g_reversible_configuration);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_WRITE,
"`lt_write_whole_R_config()` failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -1204,7 +1225,7 @@ static void prodtest_tropic_lock(cli_t* cli) {
ret = lt_read_whole_R_config(tropic_handle, &configuration_read);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_VERIFY_READ,
"`lt_read_whole_R_config()` failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -1212,13 +1233,14 @@ static void prodtest_tropic_lock(cli_t* cli) {
if (memcmp(&g_reversible_configuration, (uint8_t*)&configuration_read,
sizeof(g_reversible_configuration)) != 0) {
- cli_error(cli, CLI_ERROR, "Reversible configuration mismatch after write.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_MISMATCH,
+ "Reversible configuration mismatch after write.");
return;
}
ret = lt_write_whole_I_config(tropic_handle, &g_irreversible_configuration);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_WRITE,
"`lt_write_whole_I_config()` failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -1226,7 +1248,7 @@ static void prodtest_tropic_lock(cli_t* cli) {
ret = lt_read_whole_I_config(tropic_handle, &configuration_read);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_VERIFY_READ,
"`lt_read_whole_I_config()` failed with error '%s'",
lt_ret_verbose(ret));
return;
@@ -1234,7 +1256,7 @@ static void prodtest_tropic_lock(cli_t* cli) {
if (memcmp(&g_irreversible_configuration, (uint8_t*)&configuration_read,
sizeof(g_irreversible_configuration)) != 0) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_MISMATCH,
"Irreversible configuration mismatch after write.");
return;
}
@@ -1346,7 +1368,8 @@ static bool check_device_cert_chain(cli_t* cli, const uint8_t* chain,
lt_ret_t ret = lt_ecc_eddsa_sign(tropic_get_handle(), TROPIC_DEVICE_KEY_SLOT,
challenge, sizeof(challenge), signature);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_ecc_eddsa_sign()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_SIGN,
+ "`lt_ecc_eddsa_sign()` failed with error '%s'",
lt_ret_verbose(ret));
return false;
}
@@ -1370,9 +1393,11 @@ static void cert_write(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
if (!cli_arg_hex(cli, "hex-data", certificate, sizeof(certificate),
&certificate_length)) {
if (certificate_length == sizeof(certificate)) {
- cli_error(cli, CLI_ERROR, "Certificate too long.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_TOO_LONG,
+ "Certificate too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
@@ -1382,7 +1407,7 @@ static void cert_write(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
lt_ret_t ret =
tropic_custom_session_start(cli, TROPIC_PRIVILEGED_PAIRING_KEY_SLOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_CHAIN,
"`tropic_custom_session_start()` for privileged key failed with "
"error '%s'",
lt_ret_verbose(ret));
@@ -1400,8 +1425,8 @@ static void cert_write(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
ret = data_write(tropic_handle, first_slot, slots_count, certificate,
certificate_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`data_write()` failed with error '%s'",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_DATA,
+ "`data_write()` failed with error '%s'", lt_ret_verbose(ret));
return;
}
@@ -1410,13 +1435,14 @@ static void cert_write(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
ret = data_read(tropic_handle, first_slot, slots_count, certificate_read,
sizeof(certificate_read), &certificate_read_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`data_read()` failed with error '%s'",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_READ_BACK,
+ "`data_read()` failed with error '%s'", lt_ret_verbose(ret));
return;
}
if (certificate_read_length != certificate_length ||
memcmp(certificate, certificate_read, certificate_length) != 0) {
- cli_error(cli, CLI_ERROR, "Certificate does not match the expected value");
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_WRITE_MISMATCH,
+ "Certificate does not match the expected value");
return;
}
@@ -1434,7 +1460,7 @@ static void cert_read(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
ret = tropic_custom_session_start(cli, TROPIC_PRIVILEGED_PAIRING_KEY_SLOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_READ_DATA,
"`tropic_custom_session_start()` for privileged key failed with "
"error '%s'",
lt_ret_verbose(ret));
@@ -1446,7 +1472,8 @@ static void cert_read(cli_t* cli, uint16_t first_slot, uint16_t slots_count) {
ret = data_read(tropic_get_handle(), first_slot, slots_count, certificate,
sizeof(certificate), &certificate_length);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "Reading certificate failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_CERT_READ_FAILED,
+ "Reading certificate failed with error '%s'",
lt_ret_verbose(ret));
return;
}
@@ -1481,7 +1508,7 @@ static void pubkey_read(cli_t* cli, lt_ecc_slot_t slot,
ret = tropic_custom_session_start(cli, TROPIC_PRIVILEGED_PAIRING_KEY_SLOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_PUBKEY_READ_LT,
"`tropic_custom_session_start()` for privileged key failed with "
"error '%s'",
lt_ret_verbose(ret));
@@ -1494,19 +1521,22 @@ static void pubkey_read(cli_t* cli, lt_ecc_slot_t slot,
ret = lt_ecc_key_read(tropic_get_handle(), slot, &public_key[1],
ECDSA_PUBLIC_KEY_SIZE - 1, &curve_type, &origin);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_ecc_key_read()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_PUBKEY_READ_KEY,
+ "`lt_ecc_key_read()` failed with error '%s'",
lt_ret_verbose(ret));
return;
}
if (curve_type != TR01_CURVE_P256) {
- cli_error(cli, CLI_ERROR, "Curve type is not P-256");
+ cli_error(cli, PRODTEST_ERR_TROPIC_PUBKEY_READ_CURVE,
+ "Curve type is not P-256");
return;
}
if (masking_key != NULL) {
if (ecdsa_unmask_public_key(&nist256p1, masking_key, public_key,
public_key) != 0) {
- cli_error(cli, CLI_ERROR, "key unmasking error");
+ cli_error(cli, PRODTEST_ERR_TROPIC_PUBKEY_READ_UNMASK,
+ "key unmasking error");
return;
}
}
@@ -1518,7 +1548,8 @@ static void prodtest_tropic_keyfido_read(cli_t* cli) {
#ifdef SECRET_KEY_MASKING
uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE] = {0};
if (secret_key_tropic_masking(masking_key) != sectrue) {
- cli_error(cli, CLI_ERROR, "masking key not available");
+ cli_error(cli, PRODTEST_ERR_TROPIC_KEYFIDO_READ_MASK,
+ "masking key not available");
return;
}
pubkey_read(cli, TROPIC_FIDO_KEY_SLOT, masking_key);
@@ -1538,7 +1569,7 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
lt_chip_id_t chip_id = {0};
if (lt_get_info_chip_id(h, &chip_id) != LT_OK) {
- cli_error(cli, CLI_ERROR, "Unable to get CHIP ID");
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_CHIP_ID, "Unable to get CHIP ID");
return;
}
@@ -1548,11 +1579,13 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
#ifdef LT_SILICON_REV_ABAB
if (strncmp((char*)chip_id.silicon_rev, "ABAB", 4) != 0) {
- cli_error(cli, CLI_ERROR, "Wrong tropic chip silicon revision");
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_WRONG_REVISION,
+ "Wrong tropic chip silicon revision");
return;
}
#else
- cli_error(cli, CLI_ERROR, "Tropic chip silicon revision not set");
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_NO_REVISION,
+ "Tropic chip silicon revision not set");
return;
#endif
@@ -1560,8 +1593,8 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
cli_trace(cli, "Rebooting into Maintenance mode");
lt_ret_t ret = lt_reboot(h, TR01_MAINTENANCE_REBOOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "lt_reboot() failed, ret=%s",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_REBOOT_MAINTENANCE,
+ "lt_reboot() failed, ret=%s", lt_ret_verbose(ret));
return;
}
@@ -1571,7 +1604,8 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
ret = lt_do_mutable_fw_update(h, fw_CPU, sizeof(fw_CPU), fw_SPECT,
sizeof(fw_SPECT));
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "FW update failed, ret=%s", lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_FW, "FW update failed, ret=%s",
+ lt_ret_verbose(ret));
goto cleanup;
}
@@ -1579,8 +1613,8 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
cli_trace(cli, "Rebooting into Application mode");
ret = lt_reboot(h, TR01_REBOOT);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "lt_reboot() failed, ret=%s",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_REBOOT_APP,
+ "lt_reboot() failed, ret=%s", lt_ret_verbose(ret));
goto cleanup;
}
@@ -1590,8 +1624,8 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
ret = lt_get_info_riscv_fw_ver(h, risc_fw_ver);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get RISC-V FW version, ret=%s",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_RISCV_VERSION,
+ "Failed to get RISC-V FW version, ret=%s", lt_ret_verbose(ret));
goto cleanup;
}
@@ -1604,8 +1638,8 @@ static void prodtest_tropic_update_fw(cli_t* cli) {
ret = lt_get_info_spect_fw_ver(h, spect_fw_ver);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "Failed to get SPECT FW version, ret=%s",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_UPDATE_SPECT_VERSION,
+ "Failed to get SPECT FW version, ret=%s", lt_ret_verbose(ret));
goto cleanup;
}
@@ -1702,12 +1736,13 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
for (int i = 0; i < init_iterations; i++) {
tropic_deinit();
if (!tropic_init()) {
- cli_error(cli, CLI_ERROR, "Call #%d of `tropic_init()` failed", i + 1);
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_INIT,
+ "Call #%d of `tropic_init()` failed", i + 1);
return;
}
if (!tropic_wait_for_ready(cli)) {
- cli_error(cli, CLI_ERROR, "Call #%d of `tropic_wait_for_ready()` failed",
- i + 1);
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_READY,
+ "Call #%d of `tropic_wait_for_ready()` failed", i + 1);
return;
}
}
@@ -1716,7 +1751,8 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
lt_pkey_index_t pairing_key_index = -1;
if (!find_pairing_key(cli, &pairing_key_index)) {
- cli_error(cli, CLI_ERROR, "No pairing key is available");
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_NO_PAIRING_KEY,
+ "No pairing key is available");
return;
}
@@ -1727,14 +1763,14 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
res = tropic_session_invalidate();
if (res != LT_OK) {
cli_error(
- cli, CLI_ERROR,
+ cli, PRODTEST_ERR_TROPIC_STRESS_SESSION_INVALIDATE,
"`Call #%d of tropic_session_invalidate() failed with error '%s'",
i + 1, lt_ret_verbose(res));
return;
}
res = tropic_custom_session_start(cli, pairing_key_index);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_SESSION_START,
"Call #%d of `tropic_custom_session_start()"
"failed with error '%s'",
i + 1, lt_ret_verbose(res));
@@ -1752,7 +1788,7 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
rng_fill_buffer(buffer, sizeof(buffer));
res = lt_mac_and_destroy(tropic_get_handle(), slot_index, buffer, buffer);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_SIGN_FAILED,
"Call #%d of `lt_mac_and_destroy()` for slot %d failed "
"with error '%s'",
i + 1, slot_index, lt_ret_verbose(res));
@@ -1767,7 +1803,8 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
lt_ecc_slot_t ecc_slot = TR01_ECC_SLOT_31;
res = lt_ecc_key_generate(tropic_get_handle(), ecc_slot, TR01_CURVE_ED25519);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_ecc_key_generate()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_KEY_GENERATE,
+ "`lt_ecc_key_generate()` failed with error '%s'",
lt_ret_verbose(res));
return;
}
@@ -1776,7 +1813,7 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
res = lt_ecc_eddsa_sign(tropic_get_handle(), ecc_slot, message,
sizeof(message), signature);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_EDDSA_SIGN,
"Call #%d of `lt_ecc_eddsa_sign()` failed with error '%s'",
i + 1, lt_ret_verbose(res));
lt_ecc_key_erase(tropic_get_handle(), ecc_slot);
@@ -1785,7 +1822,8 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
}
res = lt_ecc_key_erase(tropic_get_handle(), ecc_slot);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_ecc_key_erase()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_KEY_ERASE,
+ "`lt_ecc_key_erase()` failed with error '%s'",
lt_ret_verbose(res));
return;
}
@@ -1796,7 +1834,7 @@ static void prodtest_tropic_stress_test(cli_t* cli) {
res = lt_random_value_get(tropic_get_handle(), random_value,
sizeof(random_value));
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_STRESS_RANDOM_GET,
"Call #%d of `lt_random_value_get()` failed with error '%s'",
i + 1, lt_ret_verbose(res));
return;
@@ -1818,7 +1856,8 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
lt_pkey_index_t pairing_key_index = -1;
if (!find_pairing_key(cli, &pairing_key_index)) {
- cli_error(cli, CLI_ERROR, "No pairing key is available");
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_NO_PAIRING_KEY,
+ "No pairing key is available");
return;
}
@@ -1832,7 +1871,8 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
// Ensure data slot is empty before the first iteration
res = lt_r_mem_data_erase(h, timing_data_slot);
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_r_mem_data_erase()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MEM_ERASE,
+ "`lt_r_mem_data_erase()` failed with error '%s'",
lt_ret_verbose(res));
return;
}
@@ -1852,7 +1892,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
{
res = tropic_session_invalidate();
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_INVALIDATE,
"`tropic_session_invalidate()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1861,7 +1901,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = tropic_custom_session_start(cli, pairing_key_index);
total_session_start_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_START,
"`tropic_custom_session_start()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1877,7 +1917,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
h, TROPIC_FIRST_MAC_AND_DESTROY_SLOT_UNPRIVILEGED, buffer, buffer);
total_mac_and_destroy_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MAC_AND_DESTROY,
"`lt_mac_and_destroy()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1893,7 +1933,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_r_mem_data_write(h, timing_data_slot, data, sizeof(data));
total_r_mem_data_write_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MEM_WRITE,
"`lt_r_mem_data_write()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1908,7 +1948,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
&read_size);
total_r_mem_data_read_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MEM_READ,
"`lt_r_mem_data_read()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1921,7 +1961,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_r_mem_data_erase(h, timing_data_slot);
total_r_mem_data_erase_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MEM_ERASE,
"`lt_r_mem_data_erase()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1934,7 +1974,8 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_mcounter_init(h, timing_mcounter_slot, 1);
total_mcounter_init_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_mcounter_init()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_INIT,
+ "`lt_mcounter_init()` failed with error '%s'",
lt_ret_verbose(res));
return;
}
@@ -1947,7 +1988,8 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_mcounter_get(h, timing_mcounter_slot, &counter_value);
total_mcounter_get_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_mcounter_get()` failed with error '%s'",
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_GET,
+ "`lt_mcounter_get()` failed with error '%s'",
lt_ret_verbose(res));
return;
}
@@ -1959,7 +2001,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_mcounter_update(h, timing_mcounter_slot);
total_mcounter_update_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_UPDATE,
"`lt_mcounter_update()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -1973,7 +2015,7 @@ static void prodtest_tropic_benchmark(cli_t* cli) {
res = lt_random_value_get(h, buffer, sizeof(buffer));
total_random_value_get_ms += systick_ms() - start_ms;
if (res != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_BENCHMARK_RANDOM_GET,
"`lt_random_value_get()` failed with error '%s'",
lt_ret_verbose(res));
return;
@@ -2067,7 +2109,8 @@ static void prodtest_tropic_erase_all_slots(cli_t* cli) {
}
if (!privileged_session_start(cli)) {
- cli_error(cli, CLI_ERROR, "`privileged_session_start()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_ERASE_SLOTS_SESSION,
+ "`privileged_session_start()` failed.");
return;
}
@@ -2077,7 +2120,7 @@ static void prodtest_tropic_erase_all_slots(cli_t* cli) {
if (ret == LT_OK) {
cli_ok(cli, "");
} else {
- cli_error(cli, CLI_ERROR, "Erase operation failed");
+ cli_error(cli, PRODTEST_ERR_TROPIC_ERASE_SLOTS, "Erase operation failed");
}
}
@@ -2091,15 +2134,17 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
size_t input_length = 0;
if (!cli_arg_hex(cli, "hex-data", input, sizeof(input), &input_length)) {
if (input_length == sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Input too long.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LONG, "Input too long.");
} else {
- cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_HEX_DECODE,
+ "Hexadecimal decoding error.");
}
return;
}
if (input_length != sizeof(input)) {
- cli_error(cli, CLI_ERROR, "Expected 4 bytes (8 hex digits) for uint32.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_INPUT_LEN,
+ "Expected 4 bytes (8 hex digits) for uint32.");
return;
}
@@ -2108,7 +2153,8 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
((uint32_t)input[2] << 8) | ((uint32_t)input[3]);
if (!privileged_session_start(cli)) {
- cli_error(cli, CLI_ERROR, "`privileged_session_start()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_SESSION,
+ "`privileged_session_start()` failed.");
return;
}
@@ -2116,14 +2162,15 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
lt_ret_t ret = tropic_erase_all_slots_internal(cli, tropic_handle);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "Erase operation failed");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_ERASE, "Erase operation failed");
return;
}
struct lt_config_t configuration = {0};
ret = lt_read_whole_R_config_retry(tropic_handle, &configuration);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_read_whole_R_config()` failed with error %s",
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_READ_CONFIG,
+ "`lt_read_whole_R_config()` failed with error %s",
lt_ret_verbose(ret));
return;
}
@@ -2133,7 +2180,7 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
ret = lt_erase_and_write_R_config_retry(tropic_handle, &configuration);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_SLOT_WRITE,
"`lt_erase_and_write_R_config_retry()` failed with error %s",
lt_ret_verbose(ret));
return;
@@ -2143,7 +2190,7 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
struct lt_config_t verify_configuration = {0};
ret = lt_read_whole_R_config_retry(tropic_handle, &verify_configuration);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR,
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_SLOT_READ,
"`lt_r_config_read()` verification failed with error %s",
lt_ret_verbose(ret));
return;
@@ -2151,7 +2198,8 @@ static void prodtest_tropic_set_sensors(cli_t* cli) {
if (memcmp(&configuration, &verify_configuration,
sizeof(verify_configuration)) != 0) {
- cli_error(cli, CLI_ERROR, "Configuration was not written correctly.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_SENSORS_WRITE_VERIFY,
+ "Configuration was not written correctly.");
return;
}
@@ -2167,7 +2215,8 @@ static void prodtest_tropic_read_sensors(cli_t* cli) {
lt_handle_t* tropic_handle = tropic_get_handle();
if (!privileged_session_start(cli)) {
- cli_error(cli, CLI_ERROR, "`privileged_session_start()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_READ_SENSORS_SESSION,
+ "`privileged_session_start()` failed.");
return;
}
@@ -2176,8 +2225,8 @@ static void prodtest_tropic_read_sensors(cli_t* cli) {
lt_ret_t ret =
lt_r_config_read(tropic_handle, TR01_CFG_SENSORS_ADDR, &sensors_config);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_r_config_read()` failed with error %s",
- lt_ret_verbose(ret));
+ cli_error(cli, PRODTEST_ERR_TROPIC_READ_SENSORS_CONFIG,
+ "`lt_r_config_read()` failed with error %s", lt_ret_verbose(ret));
return;
}
@@ -2193,7 +2242,8 @@ static void prodtest_tropic_read_configs(cli_t* cli) {
lt_handle_t* tropic_handle = tropic_get_handle();
if (!privileged_session_start(cli)) {
- cli_error(cli, CLI_ERROR, "`privileged_session_start()` failed.");
+ cli_error(cli, PRODTEST_ERR_TROPIC_READ_CONFIGS_SESSION,
+ "`privileged_session_start()` failed.");
return;
}
@@ -2201,7 +2251,8 @@ static void prodtest_tropic_read_configs(cli_t* cli) {
struct lt_config_t r_config = {0};
lt_ret_t ret = lt_read_whole_R_config_retry(tropic_handle, &r_config);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_read_whole_R_config()` failed with error %s",
+ cli_error(cli, PRODTEST_ERR_TROPIC_READ_CONFIGS_R_CONFIG,
+ "`lt_read_whole_R_config()` failed with error %s",
lt_ret_verbose(ret));
return;
}
@@ -2216,7 +2267,8 @@ static void prodtest_tropic_read_configs(cli_t* cli) {
struct lt_config_t i_config = {0};
ret = lt_read_whole_I_config(tropic_handle, &i_config);
if (ret != LT_OK) {
- cli_error(cli, CLI_ERROR, "`lt_read_whole_I_config()` failed with error %s",
+ cli_error(cli, PRODTEST_ERR_TROPIC_READ_CONFIGS_I_CONFIG,
+ "`lt_read_whole_I_config()` failed with error %s",
lt_ret_verbose(ret));
return;
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_unit_test.c b/core/embed/projects/prodtest/cmd/prodtest_unit_test.c
index 845350a9..1305fe8b 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_unit_test.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_unit_test.c
@@ -24,6 +24,8 @@
#include <rtl/cli.h>
#include <rtl/unit_test.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_unit_test_list(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -68,7 +70,8 @@ static void prodtest_unit_test_run(cli_t* cli) {
if (ut_passed) {
cli_ok(cli, "");
} else {
- cli_error(cli, CLI_ERROR, "Some of the unit test failed");
+ cli_error(cli, PRODTEST_ERR_UNIT_TEST_FAILED,
+ "Some of the unit test failed");
}
}
diff --git a/core/embed/projects/prodtest/cmd/prodtest_wpc.c b/core/embed/projects/prodtest/cmd/prodtest_wpc.c
index 468885cb..891181f7 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_wpc.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_wpc.c
@@ -28,6 +28,8 @@
#include <stdlib.h>
#include "../stwlc38/stwlc38.h"
+#include "prodtest_error_codes.h"
+
static void prodtest_wpc_info(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
@@ -41,13 +43,13 @@ static void prodtest_wpc_info(cli_t* cli) {
pm_deinit();
if (!stwlc38_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize STWLC38.");
+ cli_error(cli, PRODTEST_ERR_WPC_INFO_INIT, "Failed to initialize STWLC38.");
return;
}
cli_trace(cli, "Reading STWLC38 info...");
if (!stwlc38_read_chip_info(&chip_info)) {
- cli_error(cli, CLI_ERROR, "Cannot read STWLC38 info.");
+ cli_error(cli, PRODTEST_ERR_WPC_INFO_READ, "Cannot read STWLC38 info.");
goto cleanup;
}
@@ -55,7 +57,7 @@ static void prodtest_wpc_info(cli_t* cli) {
if (!cstr_encode_hex(device_id, sizeof(device_id), chip_info.device_id,
sizeof(chip_info.device_id))) {
- cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
+ cli_error(cli, PRODTEST_ERR_WPC_BUF_SMALL, "Buffer too small.");
goto cleanup;
}
@@ -96,7 +98,8 @@ cleanup:
// initlize power manager again
status_pm = pm_init(true);
if (status_pm != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
+ cli_error(cli, PRODTEST_ERR_WPC_INFO_PM_REINIT,
+ "Failed to reinitialize power manager.");
return;
}
}
@@ -113,7 +116,8 @@ static void prodtest_wpc_update(cli_t* cli) {
pm_deinit();
if (!stwlc38_init()) {
- cli_error(cli, CLI_ERROR, "Failed to initialize STWLC38.");
+ cli_error(cli, PRODTEST_ERR_WPC_UPDATE_INIT,
+ "Failed to initialize STWLC38.");
return;
}
@@ -121,7 +125,8 @@ static void prodtest_wpc_update(cli_t* cli) {
stwlc38_chip_info_t chip_info;
if (!stwlc38_read_chip_info(&chip_info)) {
- cli_error(cli, CLI_ERROR, "Cannot read STWLC38 info.");
+ cli_error(cli, PRODTEST_ERR_WPC_UPDATE_INFO_READ,
+ "Cannot read STWLC38 info.");
goto cleanup;
}
@@ -130,7 +135,8 @@ static void prodtest_wpc_update(cli_t* cli) {
} else if (chip_info.chip_rev == STWLC38_CUT_1_3) {
cli_trace(cli, "STWLC38 chip revision 1.3");
} else {
- cli_error(cli, CLI_ERROR, "Unknown chip revision, update aborted.");
+ cli_error(cli, PRODTEST_ERR_WPC_UNKNOWN_CHIP_REVISION,
+ "Unknown chip revision, update aborted.");
goto cleanup;
}
@@ -140,7 +146,7 @@ static void prodtest_wpc_update(cli_t* cli) {
update_time = systick_ms() - update_time;
if (status == false) {
- cli_error(cli, CLI_ERROR, "Failed to update STWLC38.");
+ cli_error(cli, PRODTEST_ERR_WPC_UPDATE, "Failed to update STWLC38.");
goto cleanup;
}
@@ -155,7 +161,8 @@ cleanup:
// initlize power manager again
status_pm = pm_init(true);
if (status_pm != PM_OK) {
- cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
+ cli_error(cli, PRODTEST_ERR_WPC_UPDATE_PM_REINIT,
+ "Failed to reinitialize power manager.");
return;
}
}
diff --git a/core/embed/projects/prodtest/error_codes.json b/core/embed/projects/prodtest/error_codes.json
new file mode 100644
index 00000000..d2f57432
--- /dev/null
+++ b/core/embed/projects/prodtest/error_codes.json
@@ -0,0 +1,1740 @@
+{
+ "source": "prodtest_error_codes.h",
+ "prodtest_version": "0.3.8.0",
+ "framework_codes": [
+ {
+ "code": 10,
+ "name": "CLI_ERROR_INVALID_CMD"
+ },
+ {
+ "code": 11,
+ "name": "CLI_ERROR_INVALID_ARG"
+ },
+ {
+ "code": 12,
+ "name": "CLI_ERROR_ABORT"
+ },
+ {
+ "code": 13,
+ "name": "CLI_ERROR_FATAL"
+ },
+ {
+ "code": 14,
+ "name": "CLI_ERROR_INVALID_CRC"
+ }
+ ],
+ "modules": [
+ {
+ "module": "backup-ram",
+ "range_start": 1000,
+ "range_end": 1999
+ },
+ {
+ "module": "ble",
+ "range_start": 2000,
+ "range_end": 2999
+ },
+ {
+ "module": "bootloader",
+ "range_start": 3000,
+ "range_end": 3999
+ },
+ {
+ "module": "button",
+ "range_start": 4000,
+ "range_end": 4999
+ },
+ {
+ "module": "haptic",
+ "range_start": 5000,
+ "range_end": 5999
+ },
+ {
+ "module": "manufacturing-lock",
+ "range_start": 6000,
+ "range_end": 6999
+ },
+ {
+ "module": "nfc",
+ "range_start": 7000,
+ "range_end": 7999
+ },
+ {
+ "module": "nrf",
+ "range_start": 8000,
+ "range_end": 8999
+ },
+ {
+ "module": "optiga",
+ "range_start": 9000,
+ "range_end": 9999
+ },
+ {
+ "module": "otp",
+ "range_start": 10000,
+ "range_end": 10999
+ },
+ {
+ "module": "otp-variant",
+ "range_start": 11000,
+ "range_end": 11999
+ },
+ {
+ "module": "power-manager",
+ "range_start": 12000,
+ "range_end": 12999
+ },
+ {
+ "module": "rtc",
+ "range_start": 13000,
+ "range_end": 13999
+ },
+ {
+ "module": "sdcard",
+ "range_start": 14000,
+ "range_end": 14999
+ },
+ {
+ "module": "secrets",
+ "range_start": 15000,
+ "range_end": 15999
+ },
+ {
+ "module": "secure-channel",
+ "range_start": 16000,
+ "range_end": 16999
+ },
+ {
+ "module": "tamper",
+ "range_start": 17000,
+ "range_end": 17999
+ },
+ {
+ "module": "telemetry",
+ "range_start": 18000,
+ "range_end": 18999
+ },
+ {
+ "module": "touch",
+ "range_start": 19000,
+ "range_end": 19999
+ },
+ {
+ "module": "tropic",
+ "range_start": 20000,
+ "range_end": 20999
+ },
+ {
+ "module": "unit-test",
+ "range_start": 21000,
+ "range_end": 21999
+ },
+ {
+ "module": "wpc",
+ "range_start": 22000,
+ "range_end": 22999
+ },
+ {
+ "module": "common",
+ "range_start": 23000,
+ "range_end": 23999
+ },
+ {
+ "module": "prodtest",
+ "range_start": 24000,
+ "range_end": 24999
+ },
+ {
+ "module": "syslog",
+ "range_start": 25000,
+ "range_end": 25999
+ }
+ ],
+ "errors": [
+ {
+ "code": 1010,
+ "name": "PRODTEST_ERR_BACKUP_RAM_LIST_INIT",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1011,
+ "name": "PRODTEST_ERR_BACKUP_RAM_KEY_INFO_READ",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1012,
+ "name": "PRODTEST_ERR_BACKUP_RAM_ERASE_INIT",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1013,
+ "name": "PRODTEST_ERR_BACKUP_RAM_READ_INIT",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1014,
+ "name": "PRODTEST_ERR_BACKUP_RAM_KEY_NOT_FOUND",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1015,
+ "name": "PRODTEST_ERR_BACKUP_RAM_KEY_READ",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1016,
+ "name": "PRODTEST_ERR_BACKUP_RAM_HEX_ENCODE",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1017,
+ "name": "PRODTEST_ERR_BACKUP_RAM_DATA_TOO_LONG",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1018,
+ "name": "PRODTEST_ERR_BACKUP_RAM_HEX_DECODE",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1019,
+ "name": "PRODTEST_ERR_BACKUP_RAM_WRITE_INIT",
+ "module": "backup-ram"
+ },
+ {
+ "code": 1020,
+ "name": "PRODTEST_ERR_BACKUP_RAM_KEY_WRITE",
+ "module": "backup-ram"
+ },
+ {
+ "code": 2010,
+ "name": "PRODTEST_ERR_BLE_INIT",
+ "module": "ble"
+ },
+ {
+ "code": 2011,
+ "name": "PRODTEST_ERR_BLE_TIMER_CREATE",
+ "module": "ble"
+ },
+ {
+ "code": 2012,
+ "name": "PRODTEST_ERR_BLE_ENTER_PAIRING_MODE",
+ "module": "ble"
+ },
+ {
+ "code": 2013,
+ "name": "PRODTEST_ERR_BLE_ADV_START_TIMEOUT",
+ "module": "ble"
+ },
+ {
+ "code": 2014,
+ "name": "PRODTEST_ERR_BLE_SWITCH_OFF",
+ "module": "ble"
+ },
+ {
+ "code": 2015,
+ "name": "PRODTEST_ERR_BLE_ADV_STOP_TIMEOUT",
+ "module": "ble"
+ },
+ {
+ "code": 2016,
+ "name": "PRODTEST_ERR_BLE_MAC_READ",
+ "module": "ble"
+ },
+ {
+ "code": 2017,
+ "name": "PRODTEST_ERR_BLE_STATE_UNKNOWN",
+ "module": "ble"
+ },
+ {
+ "code": 2018,
+ "name": "PRODTEST_ERR_BLE_BONDS_ERASE",
+ "module": "ble"
+ },
+ {
+ "code": 2019,
+ "name": "PRODTEST_ERR_BLE_UNPAIR_INDEX_PARSE",
+ "module": "ble"
+ },
+ {
+ "code": 2020,
+ "name": "PRODTEST_ERR_BLE_UNPAIR_INDEX_RANGE",
+ "module": "ble"
+ },
+ {
+ "code": 2021,
+ "name": "PRODTEST_ERR_BLE_UNPAIR",
+ "module": "ble"
+ },
+ {
+ "code": 2022,
+ "name": "PRODTEST_ERR_BLE_UART_INIT",
+ "module": "ble"
+ },
+ {
+ "code": 3010,
+ "name": "PRODTEST_ERR_BOOTLOADER_NO_AUTH_HEADER",
+ "module": "bootloader"
+ },
+ {
+ "code": 3011,
+ "name": "PRODTEST_ERR_BOOTLOADER_NO_IMAGE_HEADER",
+ "module": "bootloader"
+ },
+ {
+ "code": 4010,
+ "name": "PRODTEST_ERR_BUTTON_PRESS_TIMEOUT",
+ "module": "button"
+ },
+ {
+ "code": 4011,
+ "name": "PRODTEST_ERR_BUTTON_RELEASE_TIMEOUT",
+ "module": "button"
+ },
+ {
+ "code": 4012,
+ "name": "PRODTEST_ERR_BUTTON_COMBO_PRESS_TIMEOUT",
+ "module": "button"
+ },
+ {
+ "code": 4013,
+ "name": "PRODTEST_ERR_BUTTON_COMBO_RELEASE_TIMEOUT",
+ "module": "button"
+ },
+ {
+ "code": 5010,
+ "name": "PRODTEST_ERR_HAPTIC_INIT",
+ "module": "haptic"
+ },
+ {
+ "code": 5011,
+ "name": "PRODTEST_ERR_HAPTIC_TEST",
+ "module": "haptic"
+ },
+ {
+ "code": 6010,
+ "name": "PRODTEST_ERR_MANUF_LOCK_ALREADY_SET",
+ "module": "manufacturing-lock"
+ },
+ {
+ "code": 6011,
+ "name": "PRODTEST_ERR_MANUF_LOCK_OTP_WRITE",
+ "module": "manufacturing-lock"
+ },
+ {
+ "code": 6012,
+ "name": "PRODTEST_ERR_MANUF_LOCK_OTP_LOCK",
+ "module": "manufacturing-lock"
+ },
+ {
+ "code": 7010,
+ "name": "PRODTEST_ERR_NFC_READ_CARD_INIT",
+ "module": "nfc"
+ },
+ {
+ "code": 7011,
+ "name": "PRODTEST_ERR_NFC_TECH_REG",
+ "module": "nfc"
+ },
+ {
+ "code": 7012,
+ "name": "PRODTEST_ERR_NFC_ACTIVATION",
+ "module": "nfc"
+ },
+ {
+ "code": 7013,
+ "name": "PRODTEST_ERR_NFC_READ_CARD_TIMEOUT",
+ "module": "nfc"
+ },
+ {
+ "code": 7014,
+ "name": "PRODTEST_ERR_NFC_READ_CARD_ERROR",
+ "module": "nfc"
+ },
+ {
+ "code": 7015,
+ "name": "PRODTEST_ERR_NFC_UNEXPECTED",
+ "module": "nfc"
+ },
+ {
+ "code": 7016,
+ "name": "PRODTEST_ERR_NFC_EMULATE_INIT",
+ "module": "nfc"
+ },
+ {
+ "code": 7017,
+ "name": "PRODTEST_ERR_NFC_EMULATE_ERROR",
+ "module": "nfc"
+ },
+ {
+ "code": 7018,
+ "name": "PRODTEST_ERR_NFC_WRITE_CARD_INIT",
+ "module": "nfc"
+ },
+ {
+ "code": 7019,
+ "name": "PRODTEST_ERR_NFC_WRITE_CARD_TIMEOUT",
+ "module": "nfc"
+ },
+ {
+ "code": 7020,
+ "name": "PRODTEST_ERR_NFC_WRITE_CARD_ERROR",
+ "module": "nfc"
+ },
+ {
+ "code": 7021,
+ "name": "PRODTEST_ERR_NFC_TYPE_A_ONLY",
+ "module": "nfc"
+ },
+ {
+ "code": 8010,
+ "name": "PRODTEST_ERR_NRF_SPI_COMM",
+ "module": "nrf"
+ },
+ {
+ "code": 8011,
+ "name": "PRODTEST_ERR_NRF_UART_COMM",
+ "module": "nrf"
+ },
+ {
+ "code": 8012,
+ "name": "PRODTEST_ERR_NRF_RESET",
+ "module": "nrf"
+ },
+ {
+ "code": 8013,
+ "name": "PRODTEST_ERR_NRF_BOOTLOADER_GPIO",
+ "module": "nrf"
+ },
+ {
+ "code": 8014,
+ "name": "PRODTEST_ERR_NRF_RESERVED_GPIO",
+ "module": "nrf"
+ },
+ {
+ "code": 8015,
+ "name": "PRODTEST_ERR_NRF_VERSION_READ",
+ "module": "nrf"
+ },
+ {
+ "code": 8016,
+ "name": "PRODTEST_ERR_NRF_PAIR_SECRETS_LOCKED",
+ "module": "nrf"
+ },
+ {
+ "code": 8017,
+ "name": "PRODTEST_ERR_NRF_PAIR_FAILED",
+ "module": "nrf"
+ },
+ {
+ "code": 8018,
+ "name": "PRODTEST_ERR_NRF_PAIR_VERIFY",
+ "module": "nrf"
+ },
+ {
+ "code": 9010,
+ "name": "PRODTEST_ERR_OPTIGA_SET_META_SERIALIZE",
+ "module": "optiga"
+ },
+ {
+ "code": 9011,
+ "name": "PRODTEST_ERR_OPTIGA_SET_META_GET",
+ "module": "optiga"
+ },
+ {
+ "code": 9012,
+ "name": "PRODTEST_ERR_OPTIGA_SET_META_PARSE",
+ "module": "optiga"
+ },
+ {
+ "code": 9013,
+ "name": "PRODTEST_ERR_OPTIGA_SET_META_COMPARE",
+ "module": "optiga"
+ },
+ {
+ "code": 9014,
+ "name": "PRODTEST_ERR_OPTIGA_PAIR_SECRET",
+ "module": "optiga"
+ },
+ {
+ "code": 9015,
+ "name": "PRODTEST_ERR_OPTIGA_PAIR_SET_DATA",
+ "module": "optiga"
+ },
+ {
+ "code": 9016,
+ "name": "PRODTEST_ERR_OPTIGA_PAIR_HANDSHAKE",
+ "module": "optiga"
+ },
+ {
+ "code": 9017,
+ "name": "PRODTEST_ERR_OPTIGA_LOCK_TRUST_ANCHOR",
+ "module": "optiga"
+ },
+ {
+ "code": 9018,
+ "name": "PRODTEST_ERR_OPTIGA_STATUS_SERIALIZE",
+ "module": "optiga"
+ },
+ {
+ "code": 9019,
+ "name": "PRODTEST_ERR_OPTIGA_STATUS_PARSE",
+ "module": "optiga"
+ },
+ {
+ "code": 9020,
+ "name": "PRODTEST_ERR_OPTIGA_ID_READ",
+ "module": "optiga"
+ },
+ {
+ "code": 9021,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_READ_GET",
+ "module": "optiga"
+ },
+ {
+ "code": 9022,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_READ_SIGN",
+ "module": "optiga"
+ },
+ {
+ "code": 9023,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_WRITE_TOO_LONG",
+ "module": "optiga"
+ },
+ {
+ "code": 9024,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_WRITE_HEX_DECODE",
+ "module": "optiga"
+ },
+ {
+ "code": 9025,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_WRITE_SET",
+ "module": "optiga"
+ },
+ {
+ "code": 9026,
+ "name": "PRODTEST_ERR_OPTIGA_CERT_WRITE_VERIFY",
+ "module": "optiga"
+ },
+ {
+ "code": 9027,
+ "name": "PRODTEST_ERR_OPTIGA_PUBKEY_CALC_SSEC",
+ "module": "optiga"
+ },
+ {
+ "code": 9028,
+ "name": "PRODTEST_ERR_OPTIGA_PUBKEY_SIZE",
+ "module": "optiga"
+ },
+ {
+ "code": 9029,
+ "name": "PRODTEST_ERR_OPTIGA_PUBKEY_MASK",
+ "module": "optiga"
+ },
+ {
+ "code": 9030,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_KEY_LONG",
+ "module": "optiga"
+ },
+ {
+ "code": 9031,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_HEX",
+ "module": "optiga"
+ },
+ {
+ "code": 9032,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_LEN",
+ "module": "optiga"
+ },
+ {
+ "code": 9033,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_DECODE",
+ "module": "optiga"
+ },
+ {
+ "code": 9034,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_SSEC",
+ "module": "optiga"
+ },
+ {
+ "code": 9035,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_KEY",
+ "module": "optiga"
+ },
+ {
+ "code": 9036,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_DEC",
+ "module": "optiga"
+ },
+ {
+ "code": 9037,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_ANCHOR",
+ "module": "optiga"
+ },
+ {
+ "code": 9038,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_MASK",
+ "module": "optiga"
+ },
+ {
+ "code": 9039,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_PRIV",
+ "module": "optiga"
+ },
+ {
+ "code": 9040,
+ "name": "PRODTEST_ERR_OPTIGA_COUNTER_READ",
+ "module": "optiga"
+ },
+ {
+ "code": 9041,
+ "name": "PRODTEST_ERR_OPTIGA_KEYFIDO_READ_MASK",
+ "module": "optiga"
+ },
+ {
+ "code": 9042,
+ "name": "PRODTEST_ERR_OPTIGA_META_READ_OID_LONG",
+ "module": "optiga"
+ },
+ {
+ "code": 9043,
+ "name": "PRODTEST_ERR_OPTIGA_META_READ_HEX",
+ "module": "optiga"
+ },
+ {
+ "code": 9044,
+ "name": "PRODTEST_ERR_OPTIGA_META_READ_OID_SHORT",
+ "module": "optiga"
+ },
+ {
+ "code": 9045,
+ "name": "PRODTEST_ERR_OPTIGA_META_READ_GET",
+ "module": "optiga"
+ },
+ {
+ "code": 9046,
+ "name": "PRODTEST_ERR_OPTIGA_META_READ_PARSE",
+ "module": "optiga"
+ },
+ {
+ "code": 10010,
+ "name": "PRODTEST_ERR_OTP_READ",
+ "module": "otp"
+ },
+ {
+ "code": 10011,
+ "name": "PRODTEST_ERR_OTP_HEX_ENCODE",
+ "module": "otp"
+ },
+ {
+ "code": 10012,
+ "name": "PRODTEST_ERR_OTP_EMPTY",
+ "module": "otp"
+ },
+ {
+ "code": 10013,
+ "name": "PRODTEST_ERR_OTP_WRITE_HEX_ENCODE",
+ "module": "otp"
+ },
+ {
+ "code": 10014,
+ "name": "PRODTEST_ERR_OTP_LOCKED",
+ "module": "otp"
+ },
+ {
+ "code": 10015,
+ "name": "PRODTEST_ERR_OTP_WRITE",
+ "module": "otp"
+ },
+ {
+ "code": 10016,
+ "name": "PRODTEST_ERR_OTP_LOCK",
+ "module": "otp"
+ },
+ {
+ "code": 11010,
+ "name": "PRODTEST_ERR_OTP_VARIANT_BLOCK_READ",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11011,
+ "name": "PRODTEST_ERR_OTP_VARIANT_REWORK_BLOCK_READ",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11012,
+ "name": "PRODTEST_ERR_OTP_VARIANT_HEX_ENCODE",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11013,
+ "name": "PRODTEST_ERR_OTP_VARIANT_SECRETS_NOT_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11014,
+ "name": "PRODTEST_ERR_OTP_VARIANT_OPTIGA_NOT_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11015,
+ "name": "PRODTEST_ERR_OTP_VARIANT_TROPIC_NOT_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11016,
+ "name": "PRODTEST_ERR_OTP_VARIANT_REWORK_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11017,
+ "name": "PRODTEST_ERR_OTP_VARIANT_FIRST_NOT_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11018,
+ "name": "PRODTEST_ERR_OTP_VARIANT_REWORK_READ",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11019,
+ "name": "PRODTEST_ERR_OTP_VARIANT_REWORK_NOT_NEEDED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11020,
+ "name": "PRODTEST_ERR_OTP_VARIANT_LOCKED",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11021,
+ "name": "PRODTEST_ERR_OTP_VARIANT_WRITE_HEX_ENCODE",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11022,
+ "name": "PRODTEST_ERR_OTP_VARIANT_WRITE",
+ "module": "otp-variant"
+ },
+ {
+ "code": 11023,
+ "name": "PRODTEST_ERR_OTP_VARIANT_LOCK",
+ "module": "otp-variant"
+ },
+ {
+ "code": 12010,
+ "name": "PRODTEST_ERR_PM_STATE_GET",
+ "module": "power-manager"
+ },
+ {
+ "code": 12011,
+ "name": "PRODTEST_ERR_PM_HIBERNATE",
+ "module": "power-manager"
+ },
+ {
+ "code": 12012,
+ "name": "PRODTEST_ERR_PM_CHARGE_DISABLE",
+ "module": "power-manager"
+ },
+ {
+ "code": 12013,
+ "name": "PRODTEST_ERR_PM_CHARGE_ENABLE",
+ "module": "power-manager"
+ },
+ {
+ "code": 12014,
+ "name": "PRODTEST_ERR_PM_FUEL_GAUGE_REPORT_GET",
+ "module": "power-manager"
+ },
+ {
+ "code": 12015,
+ "name": "PRODTEST_ERR_PM_REPORT_GET",
+ "module": "power-manager"
+ },
+ {
+ "code": 12016,
+ "name": "PRODTEST_ERR_PM_EVENTS_GET",
+ "module": "power-manager"
+ },
+ {
+ "code": 12017,
+ "name": "PRODTEST_ERR_PM_REBOOT",
+ "module": "power-manager"
+ },
+ {
+ "code": 12018,
+ "name": "PRODTEST_ERR_PM_BATTERY_TEST_ABORTED",
+ "module": "power-manager"
+ },
+ {
+ "code": 12019,
+ "name": "PRODTEST_ERR_PM_BATTERY_TEST_REPORT_GET",
+ "module": "power-manager"
+ },
+ {
+ "code": 12020,
+ "name": "PRODTEST_ERR_PM_BATTERY_TEST",
+ "module": "power-manager"
+ },
+ {
+ "code": 13010,
+ "name": "PRODTEST_ERR_RTC_TIMESTAMP_GET",
+ "module": "rtc"
+ },
+ {
+ "code": 13011,
+ "name": "PRODTEST_ERR_RTC_TIME_SET",
+ "module": "rtc"
+ },
+ {
+ "code": 13012,
+ "name": "PRODTEST_ERR_RTC_TIME_GET",
+ "module": "rtc"
+ },
+ {
+ "code": 14010,
+ "name": "PRODTEST_ERR_SDCARD_NO_CARD",
+ "module": "sdcard"
+ },
+ {
+ "code": 14011,
+ "name": "PRODTEST_ERR_SDCARD_POWER_ON",
+ "module": "sdcard"
+ },
+ {
+ "code": 14012,
+ "name": "PRODTEST_ERR_SDCARD_READ_INITIAL",
+ "module": "sdcard"
+ },
+ {
+ "code": 14013,
+ "name": "PRODTEST_ERR_SDCARD_WRITE",
+ "module": "sdcard"
+ },
+ {
+ "code": 14014,
+ "name": "PRODTEST_ERR_SDCARD_READ_VERIFY",
+ "module": "sdcard"
+ },
+ {
+ "code": 14015,
+ "name": "PRODTEST_ERR_SDCARD_DATA_MISMATCH",
+ "module": "sdcard"
+ },
+ {
+ "code": 15010,
+ "name": "PRODTEST_ERR_SECRETS_SECTOR_ALREADY_LOCKED",
+ "module": "secrets"
+ },
+ {
+ "code": 15011,
+ "name": "PRODTEST_ERR_SECRETS_OPTIGA_ALREADY_LOCKED",
+ "module": "secrets"
+ },
+ {
+ "code": 15012,
+ "name": "PRODTEST_ERR_SECRETS_TROPIC_PAIRING_STARTED",
+ "module": "secrets"
+ },
+ {
+ "code": 15013,
+ "name": "PRODTEST_ERR_SECRETS_TROPIC_SESSION",
+ "module": "secrets"
+ },
+ {
+ "code": 15014,
+ "name": "PRODTEST_ERR_SECRETS_MASTER_KEY_PRIV",
+ "module": "secrets"
+ },
+ {
+ "code": 15015,
+ "name": "PRODTEST_ERR_SECRETS_MASTER_KEY_UNPRIV",
+ "module": "secrets"
+ },
+ {
+ "code": 15016,
+ "name": "PRODTEST_ERR_SECRETS_OPTIGA_PAIRING",
+ "module": "secrets"
+ },
+ {
+ "code": 15017,
+ "name": "PRODTEST_ERR_SECRETS_DEVICE_KEY_AUTH",
+ "module": "secrets"
+ },
+ {
+ "code": 15018,
+ "name": "PRODTEST_ERR_SECRETS_DEVICE_KEY_KEYPAIR",
+ "module": "secrets"
+ },
+ {
+ "code": 15019,
+ "name": "PRODTEST_ERR_SECRETS_DEVICE_KEY_ENCRYPT",
+ "module": "secrets"
+ },
+ {
+ "code": 15020,
+ "name": "PRODTEST_ERR_SECRETS_CERT_CHAIN_AUTH",
+ "module": "secrets"
+ },
+ {
+ "code": 15021,
+ "name": "PRODTEST_ERR_SECRETS_CERT_CHAIN_KEYPAIR",
+ "module": "secrets"
+ },
+ {
+ "code": 15022,
+ "name": "PRODTEST_ERR_SECRETS_SIGN_SIGNATURE",
+ "module": "secrets"
+ },
+ {
+ "code": 15023,
+ "name": "PRODTEST_ERR_SECRETS_CERTDEV_WRITE_NOT_IMPL",
+ "module": "secrets"
+ },
+ {
+ "code": 15024,
+ "name": "PRODTEST_ERR_SECRETS_CERT_TOO_LONG",
+ "module": "secrets"
+ },
+ {
+ "code": 15025,
+ "name": "PRODTEST_ERR_SECRETS_CERT_HEX_DECODE",
+ "module": "secrets"
+ },
+ {
+ "code": 15026,
+ "name": "PRODTEST_ERR_SECRETS_WRITE",
+ "module": "secrets"
+ },
+ {
+ "code": 15027,
+ "name": "PRODTEST_ERR_SECRETS_CERTDEV_READ_NOT_IMPL",
+ "module": "secrets"
+ },
+ {
+ "code": 15028,
+ "name": "PRODTEST_ERR_SECRETS_READ",
+ "module": "secrets"
+ },
+ {
+ "code": 15029,
+ "name": "PRODTEST_ERR_SECRETS_INVALID_CERT",
+ "module": "secrets"
+ },
+ {
+ "code": 15030,
+ "name": "PRODTEST_ERR_SECRETS_SECTOR_LOCK",
+ "module": "secrets"
+ },
+ {
+ "code": 16010,
+ "name": "PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_INIT",
+ "module": "secure-channel"
+ },
+ {
+ "code": 16011,
+ "name": "PRODTEST_ERR_SECURE_CHANNEL_INPUT_TOO_LONG",
+ "module": "secure-channel"
+ },
+ {
+ "code": 16012,
+ "name": "PRODTEST_ERR_SECURE_CHANNEL_HEX_DECODE",
+ "module": "secure-channel"
+ },
+ {
+ "code": 16013,
+ "name": "PRODTEST_ERR_SECURE_CHANNEL_INPUT_LEN",
+ "module": "secure-channel"
+ },
+ {
+ "code": 16014,
+ "name": "PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_FINISH",
+ "module": "secure-channel"
+ },
+ {
+ "code": 17010,
+ "name": "PRODTEST_ERR_TAMPER_INIT",
+ "module": "tamper"
+ },
+ {
+ "code": 18010,
+ "name": "PRODTEST_ERR_TELEMETRY_NOT_AVAILABLE",
+ "module": "telemetry"
+ },
+ {
+ "code": 18011,
+ "name": "PRODTEST_ERR_TELEMETRY_NOT_MANUFACTURING",
+ "module": "telemetry"
+ },
+ {
+ "code": 19010,
+ "name": "PRODTEST_ERR_TOUCH_INIT",
+ "module": "touch"
+ },
+ {
+ "code": 19011,
+ "name": "PRODTEST_ERR_TOUCH_QUADRANT_TIMEOUT",
+ "module": "touch"
+ },
+ {
+ "code": 19012,
+ "name": "PRODTEST_ERR_TOUCH_CUSTOM_TIMEOUT",
+ "module": "touch"
+ },
+ {
+ "code": 19013,
+ "name": "PRODTEST_ERR_TOUCH_UNEXPECTED_ACTIVITY",
+ "module": "touch"
+ },
+ {
+ "code": 20010,
+ "name": "PRODTEST_ERR_TROPIC_RISCV_FW_VERSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20011,
+ "name": "PRODTEST_ERR_TROPIC_SPECT_FW_VERSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20012,
+ "name": "PRODTEST_ERR_TROPIC_CHIP_ID",
+ "module": "tropic"
+ },
+ {
+ "code": 20013,
+ "name": "PRODTEST_ERR_TROPIC_CERT_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20014,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_CHECK_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20015,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_CHECK_R_CONFIG_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20016,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_CHECK_I_CONFIG_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20017,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_PUBKEY_UNPRIV",
+ "module": "tropic"
+ },
+ {
+ "code": 20018,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_PUBKEY_PRIV",
+ "module": "tropic"
+ },
+ {
+ "code": 20019,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_GET_PUBKEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20020,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_STORE_SET",
+ "module": "tropic"
+ },
+ {
+ "code": 20021,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_STORE_SK",
+ "module": "tropic"
+ },
+ {
+ "code": 20022,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_STORE_MISMATCH",
+ "module": "tropic"
+ },
+ {
+ "code": 20023,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_PRIV",
+ "module": "tropic"
+ },
+ {
+ "code": 20024,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_CERT_SIGN",
+ "module": "tropic"
+ },
+ {
+ "code": 20025,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_UNPRIV",
+ "module": "tropic"
+ },
+ {
+ "code": 20026,
+ "name": "PRODTEST_ERR_TROPIC_PAIR_IS_PAIRED_FAILED",
+ "module": "tropic"
+ },
+ {
+ "code": 20027,
+ "name": "PRODTEST_ERR_TROPIC_ACCESS_CRED_PUBKEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20028,
+ "name": "PRODTEST_ERR_TROPIC_ACCESS_CRED_GET_PUBKEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20029,
+ "name": "PRODTEST_ERR_TROPIC_ACCESS_CRED_ENCRYPT",
+ "module": "tropic"
+ },
+ {
+ "code": 20030,
+ "name": "PRODTEST_ERR_TROPIC_FIDO_KEY_MASKING",
+ "module": "tropic"
+ },
+ {
+ "code": 20031,
+ "name": "PRODTEST_ERR_TROPIC_FIDO_KEY_ENCRYPT",
+ "module": "tropic"
+ },
+ {
+ "code": 20032,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_NOT_PAIRED",
+ "module": "tropic"
+ },
+ {
+ "code": 20033,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LONG",
+ "module": "tropic"
+ },
+ {
+ "code": 20034,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_HEX_DECODE",
+ "module": "tropic"
+ },
+ {
+ "code": 20035,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LEN",
+ "module": "tropic"
+ },
+ {
+ "code": 20036,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_LEN",
+ "module": "tropic"
+ },
+ {
+ "code": 20037,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_DAMAGED",
+ "module": "tropic"
+ },
+ {
+ "code": 20038,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_SEND",
+ "module": "tropic"
+ },
+ {
+ "code": 20039,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_L2_SEND",
+ "module": "tropic"
+ },
+ {
+ "code": 20040,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_L2_RECEIVE",
+ "module": "tropic"
+ },
+ {
+ "code": 20041,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_LEN",
+ "module": "tropic"
+ },
+ {
+ "code": 20042,
+ "name": "PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_DAMAGED",
+ "module": "tropic"
+ },
+ {
+ "code": 20043,
+ "name": "PRODTEST_ERR_TROPIC_CMD_INPUT_LONG",
+ "module": "tropic"
+ },
+ {
+ "code": 20044,
+ "name": "PRODTEST_ERR_TROPIC_CMD_HEX_DECODE",
+ "module": "tropic"
+ },
+ {
+ "code": 20045,
+ "name": "PRODTEST_ERR_TROPIC_CMD_NO_HANDSHAKE",
+ "module": "tropic"
+ },
+ {
+ "code": 20046,
+ "name": "PRODTEST_ERR_TROPIC_CMD_L3_LEN_REQ",
+ "module": "tropic"
+ },
+ {
+ "code": 20047,
+ "name": "PRODTEST_ERR_TROPIC_CMD_REQ_DAMAGED",
+ "module": "tropic"
+ },
+ {
+ "code": 20048,
+ "name": "PRODTEST_ERR_TROPIC_CMD_SEND",
+ "module": "tropic"
+ },
+ {
+ "code": 20049,
+ "name": "PRODTEST_ERR_TROPIC_CMD_RECEIVE",
+ "module": "tropic"
+ },
+ {
+ "code": 20050,
+ "name": "PRODTEST_ERR_TROPIC_CMD_L3_LEN_RSP",
+ "module": "tropic"
+ },
+ {
+ "code": 20051,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_NOT_PAIRED",
+ "module": "tropic"
+ },
+ {
+ "code": 20052,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_INIT",
+ "module": "tropic"
+ },
+ {
+ "code": 20053,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_ERASE",
+ "module": "tropic"
+ },
+ {
+ "code": 20054,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_WRITE",
+ "module": "tropic"
+ },
+ {
+ "code": 20055,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_VERIFY_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20056,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_MISMATCH",
+ "module": "tropic"
+ },
+ {
+ "code": 20057,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_WRITE",
+ "module": "tropic"
+ },
+ {
+ "code": 20058,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_VERIFY_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20059,
+ "name": "PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_MISMATCH",
+ "module": "tropic"
+ },
+ {
+ "code": 20060,
+ "name": "PRODTEST_ERR_TROPIC_CERT_SIGN",
+ "module": "tropic"
+ },
+ {
+ "code": 20061,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_TOO_LONG",
+ "module": "tropic"
+ },
+ {
+ "code": 20062,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_HEX_DECODE",
+ "module": "tropic"
+ },
+ {
+ "code": 20063,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_CHAIN",
+ "module": "tropic"
+ },
+ {
+ "code": 20064,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_DATA",
+ "module": "tropic"
+ },
+ {
+ "code": 20065,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_READ_BACK",
+ "module": "tropic"
+ },
+ {
+ "code": 20066,
+ "name": "PRODTEST_ERR_TROPIC_CERT_WRITE_MISMATCH",
+ "module": "tropic"
+ },
+ {
+ "code": 20067,
+ "name": "PRODTEST_ERR_TROPIC_CERT_READ_DATA",
+ "module": "tropic"
+ },
+ {
+ "code": 20068,
+ "name": "PRODTEST_ERR_TROPIC_CERT_READ_FAILED",
+ "module": "tropic"
+ },
+ {
+ "code": 20069,
+ "name": "PRODTEST_ERR_TROPIC_PUBKEY_READ_LT",
+ "module": "tropic"
+ },
+ {
+ "code": 20070,
+ "name": "PRODTEST_ERR_TROPIC_PUBKEY_READ_KEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20071,
+ "name": "PRODTEST_ERR_TROPIC_PUBKEY_READ_CURVE",
+ "module": "tropic"
+ },
+ {
+ "code": 20072,
+ "name": "PRODTEST_ERR_TROPIC_PUBKEY_READ_UNMASK",
+ "module": "tropic"
+ },
+ {
+ "code": 20073,
+ "name": "PRODTEST_ERR_TROPIC_KEYFIDO_READ_MASK",
+ "module": "tropic"
+ },
+ {
+ "code": 20074,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_CHIP_ID",
+ "module": "tropic"
+ },
+ {
+ "code": 20075,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_WRONG_REVISION",
+ "module": "tropic"
+ },
+ {
+ "code": 20076,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_NO_REVISION",
+ "module": "tropic"
+ },
+ {
+ "code": 20077,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_REBOOT_MAINTENANCE",
+ "module": "tropic"
+ },
+ {
+ "code": 20078,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_FW",
+ "module": "tropic"
+ },
+ {
+ "code": 20079,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_REBOOT_APP",
+ "module": "tropic"
+ },
+ {
+ "code": 20080,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_RISCV_VERSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20081,
+ "name": "PRODTEST_ERR_TROPIC_UPDATE_SPECT_VERSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20082,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_INIT",
+ "module": "tropic"
+ },
+ {
+ "code": 20083,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_READY",
+ "module": "tropic"
+ },
+ {
+ "code": 20084,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20085,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_NO_PAIRING_KEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20086,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_SESSION_INVALIDATE",
+ "module": "tropic"
+ },
+ {
+ "code": 20087,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_SESSION_START",
+ "module": "tropic"
+ },
+ {
+ "code": 20088,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_SIGN_FAILED",
+ "module": "tropic"
+ },
+ {
+ "code": 20089,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_KEY_GENERATE",
+ "module": "tropic"
+ },
+ {
+ "code": 20090,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_EDDSA_SIGN",
+ "module": "tropic"
+ },
+ {
+ "code": 20091,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_KEY_ERASE",
+ "module": "tropic"
+ },
+ {
+ "code": 20092,
+ "name": "PRODTEST_ERR_TROPIC_STRESS_RANDOM_GET",
+ "module": "tropic"
+ },
+ {
+ "code": 20093,
+ "name": "PRODTEST_ERR_TROPIC_ERASE_SLOTS_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20094,
+ "name": "PRODTEST_ERR_TROPIC_ERASE_SLOTS",
+ "module": "tropic"
+ },
+ {
+ "code": 20095,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_INPUT_LONG",
+ "module": "tropic"
+ },
+ {
+ "code": 20096,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_HEX_DECODE",
+ "module": "tropic"
+ },
+ {
+ "code": 20097,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_INPUT_LEN",
+ "module": "tropic"
+ },
+ {
+ "code": 20098,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20099,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_ERASE",
+ "module": "tropic"
+ },
+ {
+ "code": 20100,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_READ_CONFIG",
+ "module": "tropic"
+ },
+ {
+ "code": 20101,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_SLOT_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20102,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_SLOT_WRITE",
+ "module": "tropic"
+ },
+ {
+ "code": 20103,
+ "name": "PRODTEST_ERR_TROPIC_SENSORS_WRITE_VERIFY",
+ "module": "tropic"
+ },
+ {
+ "code": 20104,
+ "name": "PRODTEST_ERR_TROPIC_READ_SENSORS_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20105,
+ "name": "PRODTEST_ERR_TROPIC_READ_SENSORS_CONFIG",
+ "module": "tropic"
+ },
+ {
+ "code": 20106,
+ "name": "PRODTEST_ERR_TROPIC_READ_CONFIGS_SESSION",
+ "module": "tropic"
+ },
+ {
+ "code": 20107,
+ "name": "PRODTEST_ERR_TROPIC_READ_CONFIGS_R_CONFIG",
+ "module": "tropic"
+ },
+ {
+ "code": 20108,
+ "name": "PRODTEST_ERR_TROPIC_READ_CONFIGS_I_CONFIG",
+ "module": "tropic"
+ },
+ {
+ "code": 20109,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_NO_PAIRING_KEY",
+ "module": "tropic"
+ },
+ {
+ "code": 20110,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MEM_ERASE",
+ "module": "tropic"
+ },
+ {
+ "code": 20111,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_INVALIDATE",
+ "module": "tropic"
+ },
+ {
+ "code": 20112,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_START",
+ "module": "tropic"
+ },
+ {
+ "code": 20113,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MAC_AND_DESTROY",
+ "module": "tropic"
+ },
+ {
+ "code": 20114,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MEM_WRITE",
+ "module": "tropic"
+ },
+ {
+ "code": 20115,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MEM_READ",
+ "module": "tropic"
+ },
+ {
+ "code": 20116,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_INIT",
+ "module": "tropic"
+ },
+ {
+ "code": 20117,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_GET",
+ "module": "tropic"
+ },
+ {
+ "code": 20118,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_UPDATE",
+ "module": "tropic"
+ },
+ {
+ "code": 20119,
+ "name": "PRODTEST_ERR_TROPIC_BENCHMARK_RANDOM_GET",
+ "module": "tropic"
+ },
+ {
+ "code": 21010,
+ "name": "PRODTEST_ERR_UNIT_TEST_FAILED",
+ "module": "unit-test"
+ },
+ {
+ "code": 22010,
+ "name": "PRODTEST_ERR_WPC_INFO_INIT",
+ "module": "wpc"
+ },
+ {
+ "code": 22011,
+ "name": "PRODTEST_ERR_WPC_INFO_READ",
+ "module": "wpc"
+ },
+ {
+ "code": 22012,
+ "name": "PRODTEST_ERR_WPC_BUF_SMALL",
+ "module": "wpc"
+ },
+ {
+ "code": 22013,
+ "name": "PRODTEST_ERR_WPC_INFO_PM_REINIT",
+ "module": "wpc"
+ },
+ {
+ "code": 22014,
+ "name": "PRODTEST_ERR_WPC_UPDATE_INIT",
+ "module": "wpc"
+ },
+ {
+ "code": 22015,
+ "name": "PRODTEST_ERR_WPC_UPDATE_INFO_READ",
+ "module": "wpc"
+ },
+ {
+ "code": 22016,
+ "name": "PRODTEST_ERR_WPC_UNKNOWN_CHIP_REVISION",
+ "module": "wpc"
+ },
+ {
+ "code": 22017,
+ "name": "PRODTEST_ERR_WPC_UPDATE",
+ "module": "wpc"
+ },
+ {
+ "code": 22018,
+ "name": "PRODTEST_ERR_WPC_UPDATE_PM_REINIT",
+ "module": "wpc"
+ },
+ {
+ "code": 23010,
+ "name": "PRODTEST_ERR_COMMON_CERT_EXTENSIONS",
+ "module": "common"
+ },
+ {
+ "code": 23011,
+ "name": "PRODTEST_ERR_COMMON_CERT_AUTH_KEY_NOT_FOUND",
+ "module": "common"
+ },
+ {
+ "code": 23012,
+ "name": "PRODTEST_ERR_COMMON_CERT_AUTH_KEY_EXTNVALUE",
+ "module": "common"
+ },
+ {
+ "code": 23013,
+ "name": "PRODTEST_ERR_COMMON_CERT_AUTH_KEY_FIELD",
+ "module": "common"
+ },
+ {
+ "code": 23014,
+ "name": "PRODTEST_ERR_COMMON_CERT_AUTH_KEY_LEN",
+ "module": "common"
+ },
+ {
+ "code": 23015,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_CERT",
+ "module": "common"
+ },
+ {
+ "code": 23016,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS",
+ "module": "common"
+ },
+ {
+ "code": 23017,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS_PRELUDE",
+ "module": "common"
+ },
+ {
+ "code": 23018,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SUBJECT",
+ "module": "common"
+ },
+ {
+ "code": 23019,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_COMMON_NAME",
+ "module": "common"
+ },
+ {
+ "code": 23020,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_DEVICE_SN",
+ "module": "common"
+ },
+ {
+ "code": 23021,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_SERIAL_NUM",
+ "module": "common"
+ },
+ {
+ "code": 23022,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_SN_MISMATCH",
+ "module": "common"
+ },
+ {
+ "code": 23023,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SPKI",
+ "module": "common"
+ },
+ {
+ "code": 23024,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_ALGORITHM",
+ "module": "common"
+ },
+ {
+ "code": 23025,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_PUBKEY_BITS",
+ "module": "common"
+ },
+ {
+ "code": 23026,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_PUBKEY",
+ "module": "common"
+ },
+ {
+ "code": 23027,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_VERIFY_SIG",
+ "module": "common"
+ },
+ {
+ "code": 23028,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SIG_ALG",
+ "module": "common"
+ },
+ {
+ "code": 23029,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_SIG_VALUE",
+ "module": "common"
+ },
+ {
+ "code": 23030,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_DER",
+ "module": "common"
+ },
+ {
+ "code": 23031,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_ROOT",
+ "module": "common"
+ },
+ {
+ "code": 23032,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_KEY",
+ "module": "common"
+ },
+ {
+ "code": 23033,
+ "name": "PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_SIG",
+ "module": "common"
+ },
+ {
+ "code": 23034,
+ "name": "PRODTEST_ERR_COMMON_UPDATE_NOT_STARTED",
+ "module": "common"
+ },
+ {
+ "code": 23035,
+ "name": "PRODTEST_ERR_COMMON_UPDATE_NO_DATA",
+ "module": "common"
+ },
+ {
+ "code": 23036,
+ "name": "PRODTEST_ERR_COMMON_UPDATE_FINALIZE",
+ "module": "common"
+ },
+ {
+ "code": 23037,
+ "name": "PRODTEST_ERR_COMMON_UPDATE_UNKNOWN_PHASE",
+ "module": "common"
+ },
+ {
+ "code": 24010,
+ "name": "PRODTEST_ERR_PRODTEST_WIPE_BLE_BONDS_ERASE",
+ "module": "prodtest"
+ },
+ {
+ "code": 25010,
+ "name": "PRODTEST_ERR_SYSLOG_FILTER_SET",
+ "module": "syslog"
+ }
+ ]
+}
diff --git a/core/embed/projects/prodtest/prodtest_error_codes.h b/core/embed/projects/prodtest/prodtest_error_codes.h
new file mode 100644
index 00000000..80467570
--- /dev/null
+++ b/core/embed/projects/prodtest/prodtest_error_codes.h
@@ -0,0 +1,432 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+// Prodtest CLI error codes.
+//
+// Each error code uniquely identifies a single call site. Codes are assigned
+// in module blocks of 1000. The first 10 codes of every block (X000–X009) are
+// reserved for future use and must be skipped; assignments start at X010.
+// Once assigned a code is NEVER reused, even if the error is removed. Retired
+// codes must remain in this file marked with a DEPRECATED comment so future
+// assignees know the value is taken.
+//
+// To add a new error: append to the relevant module block and increment the
+// last-used value. Never fill a gap left by a retired code.
+//
+// Module registry:
+// Framework CLI : 0 – 999 (defined in cli.h, not here)
+// backup-ram : 1000 – 1999
+// ble : 2000 – 2999
+// bootloader : 3000 – 3999
+// button : 4000 – 4999
+// haptic : 5000 – 5999
+// manufacturing : 6000 – 6999
+// nfc : 7000 – 7999
+// nrf : 8000 – 8999
+// optiga : 9000 – 9999
+// otp : 10000 – 10999 (otp-batch + otp-device-sn share a helper)
+// otp-variant : 11000 – 11999
+// power-manager : 12000 – 12999
+// rtc : 13000 – 13999
+// sdcard : 14000 – 14999
+// secrets : 15000 – 15999
+// secure-channel : 16000 – 16999
+// tamper : 17000 – 17999
+// telemetry : 18000 – 18999
+// touch : 19000 – 19999
+// tropic : 20000 – 20999
+// unit-test : 21000 – 21999
+// wpc : 22000 – 22999
+// common : 23000 – 23999
+// prodtest : 24000 – 24999
+// syslog : 25000 – 25999
+
+typedef enum {
+
+ // === backup-ram (1000–1999) ===
+ PRODTEST_ERR_BACKUP_RAM_LIST_INIT = 1010,
+ PRODTEST_ERR_BACKUP_RAM_KEY_INFO_READ = 1011,
+ PRODTEST_ERR_BACKUP_RAM_ERASE_INIT = 1012,
+ PRODTEST_ERR_BACKUP_RAM_READ_INIT = 1013,
+ PRODTEST_ERR_BACKUP_RAM_KEY_NOT_FOUND = 1014,
+ PRODTEST_ERR_BACKUP_RAM_KEY_READ = 1015,
+ PRODTEST_ERR_BACKUP_RAM_HEX_ENCODE = 1016,
+ PRODTEST_ERR_BACKUP_RAM_DATA_TOO_LONG = 1017,
+ PRODTEST_ERR_BACKUP_RAM_HEX_DECODE = 1018,
+ PRODTEST_ERR_BACKUP_RAM_WRITE_INIT = 1019,
+ PRODTEST_ERR_BACKUP_RAM_KEY_WRITE = 1020,
+
+ // === ble (2000–2999) ===
+ PRODTEST_ERR_BLE_INIT = 2010,
+ PRODTEST_ERR_BLE_TIMER_CREATE = 2011,
+ PRODTEST_ERR_BLE_ENTER_PAIRING_MODE = 2012,
+ PRODTEST_ERR_BLE_ADV_START_TIMEOUT = 2013,
+ PRODTEST_ERR_BLE_SWITCH_OFF = 2014,
+ PRODTEST_ERR_BLE_ADV_STOP_TIMEOUT = 2015,
+ PRODTEST_ERR_BLE_MAC_READ = 2016,
+ PRODTEST_ERR_BLE_STATE_UNKNOWN = 2017,
+ PRODTEST_ERR_BLE_BONDS_ERASE = 2018,
+ PRODTEST_ERR_BLE_UNPAIR_INDEX_PARSE = 2019,
+ PRODTEST_ERR_BLE_UNPAIR_INDEX_RANGE = 2020,
+ PRODTEST_ERR_BLE_UNPAIR = 2021,
+ PRODTEST_ERR_BLE_UART_INIT = 2022,
+
+ // === bootloader (3000–3999) ===
+ PRODTEST_ERR_BOOTLOADER_NO_AUTH_HEADER = 3010,
+ PRODTEST_ERR_BOOTLOADER_NO_IMAGE_HEADER = 3011,
+
+ // === button (4000–4999) ===
+ PRODTEST_ERR_BUTTON_PRESS_TIMEOUT = 4010,
+ PRODTEST_ERR_BUTTON_RELEASE_TIMEOUT = 4011,
+ PRODTEST_ERR_BUTTON_COMBO_PRESS_TIMEOUT = 4012,
+ PRODTEST_ERR_BUTTON_COMBO_RELEASE_TIMEOUT = 4013,
+
+ // === haptic (5000–5999) ===
+ PRODTEST_ERR_HAPTIC_INIT = 5010,
+ PRODTEST_ERR_HAPTIC_TEST = 5011,
+
+ // === manufacturing-lock (6000–6999) ===
+ PRODTEST_ERR_MANUF_LOCK_ALREADY_SET = 6010,
+ PRODTEST_ERR_MANUF_LOCK_OTP_WRITE = 6011,
+ PRODTEST_ERR_MANUF_LOCK_OTP_LOCK = 6012,
+
+ // === nfc (7000–7999) ===
+ PRODTEST_ERR_NFC_READ_CARD_INIT = 7010,
+ PRODTEST_ERR_NFC_TECH_REG = 7011,
+ PRODTEST_ERR_NFC_ACTIVATION = 7012,
+ PRODTEST_ERR_NFC_READ_CARD_TIMEOUT = 7013,
+ PRODTEST_ERR_NFC_READ_CARD_ERROR = 7014,
+ PRODTEST_ERR_NFC_UNEXPECTED = 7015,
+ PRODTEST_ERR_NFC_EMULATE_INIT = 7016,
+ PRODTEST_ERR_NFC_EMULATE_ERROR = 7017,
+ PRODTEST_ERR_NFC_WRITE_CARD_INIT = 7018,
+ PRODTEST_ERR_NFC_WRITE_CARD_TIMEOUT = 7019,
+ PRODTEST_ERR_NFC_WRITE_CARD_ERROR = 7020,
+ PRODTEST_ERR_NFC_TYPE_A_ONLY = 7021,
+
+ // === nrf (8000–8999) ===
+ PRODTEST_ERR_NRF_SPI_COMM = 8010,
+ PRODTEST_ERR_NRF_UART_COMM = 8011,
+ PRODTEST_ERR_NRF_RESET = 8012,
+ PRODTEST_ERR_NRF_BOOTLOADER_GPIO = 8013,
+ PRODTEST_ERR_NRF_RESERVED_GPIO = 8014,
+ PRODTEST_ERR_NRF_VERSION_READ = 8015,
+ PRODTEST_ERR_NRF_PAIR_SECRETS_LOCKED = 8016,
+ PRODTEST_ERR_NRF_PAIR_FAILED = 8017,
+ PRODTEST_ERR_NRF_PAIR_VERIFY = 8018,
+
+ // === optiga (9000–9999) ===
+ PRODTEST_ERR_OPTIGA_SET_META_SERIALIZE = 9010,
+ PRODTEST_ERR_OPTIGA_SET_META_GET = 9011,
+ PRODTEST_ERR_OPTIGA_SET_META_PARSE = 9012,
+ PRODTEST_ERR_OPTIGA_SET_META_COMPARE = 9013,
+ PRODTEST_ERR_OPTIGA_PAIR_SECRET = 9014,
+ PRODTEST_ERR_OPTIGA_PAIR_SET_DATA = 9015,
+ PRODTEST_ERR_OPTIGA_PAIR_HANDSHAKE = 9016,
+ PRODTEST_ERR_OPTIGA_LOCK_TRUST_ANCHOR = 9017,
+ PRODTEST_ERR_OPTIGA_STATUS_SERIALIZE = 9018,
+ PRODTEST_ERR_OPTIGA_STATUS_PARSE = 9019,
+ PRODTEST_ERR_OPTIGA_ID_READ = 9020,
+ PRODTEST_ERR_OPTIGA_CERT_READ_GET = 9021,
+ PRODTEST_ERR_OPTIGA_CERT_READ_SIGN = 9022,
+ PRODTEST_ERR_OPTIGA_CERT_WRITE_TOO_LONG = 9023,
+ PRODTEST_ERR_OPTIGA_CERT_WRITE_HEX_DECODE = 9024,
+ PRODTEST_ERR_OPTIGA_CERT_WRITE_SET = 9025,
+ PRODTEST_ERR_OPTIGA_CERT_WRITE_VERIFY = 9026,
+ PRODTEST_ERR_OPTIGA_PUBKEY_CALC_SSEC = 9027,
+ PRODTEST_ERR_OPTIGA_PUBKEY_SIZE = 9028,
+ PRODTEST_ERR_OPTIGA_PUBKEY_MASK = 9029,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_KEY_LONG = 9030,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_HEX = 9031,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_LEN = 9032,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_DECODE = 9033,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_SSEC = 9034,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_KEY = 9035,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_AES_DEC = 9036,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_ANCHOR = 9037,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_MASK = 9038,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_WRITE_PRIV = 9039,
+ PRODTEST_ERR_OPTIGA_COUNTER_READ = 9040,
+ PRODTEST_ERR_OPTIGA_KEYFIDO_READ_MASK = 9041,
+ PRODTEST_ERR_OPTIGA_META_READ_OID_LONG = 9042,
+ PRODTEST_ERR_OPTIGA_META_READ_HEX = 9043,
+ PRODTEST_ERR_OPTIGA_META_READ_OID_SHORT = 9044,
+ PRODTEST_ERR_OPTIGA_META_READ_GET = 9045,
+ PRODTEST_ERR_OPTIGA_META_READ_PARSE = 9046,
+
+ // === otp (10000–10999) === otp-batch and otp-device-sn share
+ // prodtest_otp_read/write
+ PRODTEST_ERR_OTP_READ = 10010,
+ PRODTEST_ERR_OTP_HEX_ENCODE = 10011,
+ PRODTEST_ERR_OTP_EMPTY = 10012,
+ PRODTEST_ERR_OTP_WRITE_HEX_ENCODE = 10013,
+ PRODTEST_ERR_OTP_LOCKED = 10014,
+ PRODTEST_ERR_OTP_WRITE = 10015,
+ PRODTEST_ERR_OTP_LOCK = 10016,
+
+ // === otp-variant (11000–11999) ===
+ PRODTEST_ERR_OTP_VARIANT_BLOCK_READ = 11010,
+ PRODTEST_ERR_OTP_VARIANT_REWORK_BLOCK_READ = 11011,
+ PRODTEST_ERR_OTP_VARIANT_HEX_ENCODE = 11012,
+ PRODTEST_ERR_OTP_VARIANT_SECRETS_NOT_LOCKED = 11013,
+ PRODTEST_ERR_OTP_VARIANT_OPTIGA_NOT_LOCKED = 11014,
+ PRODTEST_ERR_OTP_VARIANT_TROPIC_NOT_LOCKED = 11015,
+ PRODTEST_ERR_OTP_VARIANT_REWORK_LOCKED = 11016,
+ PRODTEST_ERR_OTP_VARIANT_FIRST_NOT_LOCKED = 11017,
+ PRODTEST_ERR_OTP_VARIANT_REWORK_READ = 11018,
+ PRODTEST_ERR_OTP_VARIANT_REWORK_NOT_NEEDED = 11019,
+ PRODTEST_ERR_OTP_VARIANT_LOCKED = 11020,
+ PRODTEST_ERR_OTP_VARIANT_WRITE_HEX_ENCODE = 11021,
+ PRODTEST_ERR_OTP_VARIANT_WRITE = 11022,
+ PRODTEST_ERR_OTP_VARIANT_LOCK = 11023,
+
+ // === power-manager (12000–12999) ===
+ PRODTEST_ERR_PM_STATE_GET = 12010,
+ PRODTEST_ERR_PM_HIBERNATE = 12011,
+ PRODTEST_ERR_PM_CHARGE_DISABLE = 12012,
+ PRODTEST_ERR_PM_CHARGE_ENABLE = 12013,
+ PRODTEST_ERR_PM_FUEL_GAUGE_REPORT_GET = 12014,
+ PRODTEST_ERR_PM_REPORT_GET = 12015,
+ PRODTEST_ERR_PM_EVENTS_GET = 12016,
+ PRODTEST_ERR_PM_REBOOT = 12017,
+ PRODTEST_ERR_PM_BATTERY_TEST_ABORTED = 12018,
+ PRODTEST_ERR_PM_BATTERY_TEST_REPORT_GET = 12019,
+ PRODTEST_ERR_PM_BATTERY_TEST = 12020,
+
+ // === rtc (13000–13999) ===
+ PRODTEST_ERR_RTC_TIMESTAMP_GET = 13010,
+ PRODTEST_ERR_RTC_TIME_SET = 13011,
+ PRODTEST_ERR_RTC_TIME_GET = 13012,
+
+ // === sdcard (14000–14999) ===
+ PRODTEST_ERR_SDCARD_NO_CARD = 14010,
+ PRODTEST_ERR_SDCARD_POWER_ON = 14011,
+ PRODTEST_ERR_SDCARD_READ_INITIAL = 14012,
+ PRODTEST_ERR_SDCARD_WRITE = 14013,
+ PRODTEST_ERR_SDCARD_READ_VERIFY = 14014,
+ PRODTEST_ERR_SDCARD_DATA_MISMATCH = 14015,
+
+ // === secrets (15000–15999) ===
+ PRODTEST_ERR_SECRETS_SECTOR_ALREADY_LOCKED = 15010,
+ PRODTEST_ERR_SECRETS_OPTIGA_ALREADY_LOCKED = 15011,
+ PRODTEST_ERR_SECRETS_TROPIC_PAIRING_STARTED = 15012,
+ PRODTEST_ERR_SECRETS_TROPIC_SESSION = 15013,
+ PRODTEST_ERR_SECRETS_MASTER_KEY_PRIV = 15014,
+ PRODTEST_ERR_SECRETS_MASTER_KEY_UNPRIV = 15015,
+ PRODTEST_ERR_SECRETS_OPTIGA_PAIRING = 15016,
+ PRODTEST_ERR_SECRETS_DEVICE_KEY_AUTH = 15017,
+ PRODTEST_ERR_SECRETS_DEVICE_KEY_KEYPAIR = 15018,
+ PRODTEST_ERR_SECRETS_DEVICE_KEY_ENCRYPT = 15019,
+ PRODTEST_ERR_SECRETS_CERT_CHAIN_AUTH = 15020,
+ PRODTEST_ERR_SECRETS_CERT_CHAIN_KEYPAIR = 15021,
+ PRODTEST_ERR_SECRETS_SIGN_SIGNATURE = 15022,
+ PRODTEST_ERR_SECRETS_CERTDEV_WRITE_NOT_IMPL = 15023,
+ PRODTEST_ERR_SECRETS_CERT_TOO_LONG = 15024,
+ PRODTEST_ERR_SECRETS_CERT_HEX_DECODE = 15025,
+ PRODTEST_ERR_SECRETS_WRITE = 15026,
+ PRODTEST_ERR_SECRETS_CERTDEV_READ_NOT_IMPL = 15027,
+ PRODTEST_ERR_SECRETS_READ = 15028,
+ PRODTEST_ERR_SECRETS_INVALID_CERT = 15029,
+ PRODTEST_ERR_SECRETS_SECTOR_LOCK = 15030,
+
+ // === secure-channel (16000–16999) ===
+ PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_INIT = 16010,
+ PRODTEST_ERR_SECURE_CHANNEL_INPUT_TOO_LONG = 16011,
+ PRODTEST_ERR_SECURE_CHANNEL_HEX_DECODE = 16012,
+ PRODTEST_ERR_SECURE_CHANNEL_INPUT_LEN = 16013,
+ PRODTEST_ERR_SECURE_CHANNEL_HANDSHAKE_FINISH = 16014,
+
+ // === tamper (17000–17999) ===
+ PRODTEST_ERR_TAMPER_INIT = 17010,
+
+ // === telemetry (18000–18999) ===
+ PRODTEST_ERR_TELEMETRY_NOT_AVAILABLE = 18010,
+ PRODTEST_ERR_TELEMETRY_NOT_MANUFACTURING = 18011,
+
+ // === touch (19000–19999) ===
+ PRODTEST_ERR_TOUCH_INIT = 19010,
+ PRODTEST_ERR_TOUCH_QUADRANT_TIMEOUT = 19011,
+ PRODTEST_ERR_TOUCH_CUSTOM_TIMEOUT = 19012,
+ PRODTEST_ERR_TOUCH_UNEXPECTED_ACTIVITY = 19013,
+
+ // === tropic (20000–20999) ===
+ PRODTEST_ERR_TROPIC_RISCV_FW_VERSION = 20010,
+ PRODTEST_ERR_TROPIC_SPECT_FW_VERSION = 20011,
+ PRODTEST_ERR_TROPIC_CHIP_ID = 20012,
+ PRODTEST_ERR_TROPIC_CERT_READ = 20013,
+ PRODTEST_ERR_TROPIC_LOCK_CHECK_SESSION = 20014,
+ PRODTEST_ERR_TROPIC_LOCK_CHECK_R_CONFIG_READ = 20015,
+ PRODTEST_ERR_TROPIC_LOCK_CHECK_I_CONFIG_READ = 20016,
+ PRODTEST_ERR_TROPIC_PAIR_PUBKEY_UNPRIV = 20017,
+ PRODTEST_ERR_TROPIC_PAIR_PUBKEY_PRIV = 20018,
+ PRODTEST_ERR_TROPIC_PAIR_GET_PUBKEY = 20019,
+ PRODTEST_ERR_TROPIC_PAIR_STORE_SET = 20020,
+ PRODTEST_ERR_TROPIC_PAIR_STORE_SK = 20021,
+ PRODTEST_ERR_TROPIC_PAIR_STORE_MISMATCH = 20022,
+ PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_PRIV = 20023,
+ PRODTEST_ERR_TROPIC_PAIR_CERT_SIGN = 20024,
+ PRODTEST_ERR_TROPIC_PAIR_KEY_WRITE_UNPRIV = 20025,
+ PRODTEST_ERR_TROPIC_PAIR_IS_PAIRED_FAILED = 20026,
+ PRODTEST_ERR_TROPIC_ACCESS_CRED_PUBKEY = 20027,
+ PRODTEST_ERR_TROPIC_ACCESS_CRED_GET_PUBKEY = 20028,
+ PRODTEST_ERR_TROPIC_ACCESS_CRED_ENCRYPT = 20029,
+ PRODTEST_ERR_TROPIC_FIDO_KEY_MASKING = 20030,
+ PRODTEST_ERR_TROPIC_FIDO_KEY_ENCRYPT = 20031,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_NOT_PAIRED = 20032,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LONG = 20033,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_HEX_DECODE = 20034,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_INPUT_LEN = 20035,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_LEN = 20036,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_REQ_DAMAGED = 20037,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_SEND = 20038,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_L2_SEND = 20039,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_L2_RECEIVE = 20040,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_LEN = 20041,
+ PRODTEST_ERR_TROPIC_HANDSHAKE_RSP_DAMAGED = 20042,
+ PRODTEST_ERR_TROPIC_CMD_INPUT_LONG = 20043,
+ PRODTEST_ERR_TROPIC_CMD_HEX_DECODE = 20044,
+ PRODTEST_ERR_TROPIC_CMD_NO_HANDSHAKE = 20045,
+ PRODTEST_ERR_TROPIC_CMD_L3_LEN_REQ = 20046,
+ PRODTEST_ERR_TROPIC_CMD_REQ_DAMAGED = 20047,
+ PRODTEST_ERR_TROPIC_CMD_SEND = 20048,
+ PRODTEST_ERR_TROPIC_CMD_RECEIVE = 20049,
+ PRODTEST_ERR_TROPIC_CMD_L3_LEN_RSP = 20050,
+ PRODTEST_ERR_TROPIC_LOCK_NOT_PAIRED = 20051,
+ PRODTEST_ERR_TROPIC_LOCK_INIT = 20052,
+ PRODTEST_ERR_TROPIC_LOCK_ERASE = 20053,
+ PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_WRITE = 20054,
+ PRODTEST_ERR_TROPIC_LOCK_R_CONFIG_VERIFY_READ = 20055,
+ PRODTEST_ERR_TROPIC_LOCK_MISMATCH = 20056,
+ PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_WRITE = 20057,
+ PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_VERIFY_READ = 20058,
+ PRODTEST_ERR_TROPIC_LOCK_I_CONFIG_MISMATCH = 20059,
+ PRODTEST_ERR_TROPIC_CERT_SIGN = 20060,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_TOO_LONG = 20061,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_HEX_DECODE = 20062,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_CHAIN = 20063,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_DATA = 20064,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_READ_BACK = 20065,
+ PRODTEST_ERR_TROPIC_CERT_WRITE_MISMATCH = 20066,
+ PRODTEST_ERR_TROPIC_CERT_READ_DATA = 20067,
+ PRODTEST_ERR_TROPIC_CERT_READ_FAILED = 20068,
+ PRODTEST_ERR_TROPIC_PUBKEY_READ_LT = 20069,
+ PRODTEST_ERR_TROPIC_PUBKEY_READ_KEY = 20070,
+ PRODTEST_ERR_TROPIC_PUBKEY_READ_CURVE = 20071,
+ PRODTEST_ERR_TROPIC_PUBKEY_READ_UNMASK = 20072,
+ PRODTEST_ERR_TROPIC_KEYFIDO_READ_MASK = 20073,
+ PRODTEST_ERR_TROPIC_UPDATE_CHIP_ID = 20074,
+ PRODTEST_ERR_TROPIC_UPDATE_WRONG_REVISION = 20075,
+ PRODTEST_ERR_TROPIC_UPDATE_NO_REVISION = 20076,
+ PRODTEST_ERR_TROPIC_UPDATE_REBOOT_MAINTENANCE = 20077,
+ PRODTEST_ERR_TROPIC_UPDATE_FW = 20078,
+ PRODTEST_ERR_TROPIC_UPDATE_REBOOT_APP = 20079,
+ PRODTEST_ERR_TROPIC_UPDATE_RISCV_VERSION = 20080,
+ PRODTEST_ERR_TROPIC_UPDATE_SPECT_VERSION = 20081,
+ PRODTEST_ERR_TROPIC_STRESS_INIT = 20082,
+ PRODTEST_ERR_TROPIC_STRESS_READY = 20083,
+ PRODTEST_ERR_TROPIC_STRESS_SESSION = 20084,
+ PRODTEST_ERR_TROPIC_STRESS_NO_PAIRING_KEY = 20085,
+ PRODTEST_ERR_TROPIC_STRESS_SESSION_INVALIDATE = 20086,
+ PRODTEST_ERR_TROPIC_STRESS_SESSION_START = 20087,
+ PRODTEST_ERR_TROPIC_STRESS_SIGN_FAILED = 20088,
+ PRODTEST_ERR_TROPIC_STRESS_KEY_GENERATE = 20089,
+ PRODTEST_ERR_TROPIC_STRESS_EDDSA_SIGN = 20090,
+ PRODTEST_ERR_TROPIC_STRESS_KEY_ERASE = 20091,
+ PRODTEST_ERR_TROPIC_STRESS_RANDOM_GET = 20092,
+ PRODTEST_ERR_TROPIC_ERASE_SLOTS_SESSION = 20093,
+ PRODTEST_ERR_TROPIC_ERASE_SLOTS = 20094,
+ PRODTEST_ERR_TROPIC_SENSORS_INPUT_LONG = 20095,
+ PRODTEST_ERR_TROPIC_SENSORS_HEX_DECODE = 20096,
+ PRODTEST_ERR_TROPIC_SENSORS_INPUT_LEN = 20097,
+ PRODTEST_ERR_TROPIC_SENSORS_SESSION = 20098,
+ PRODTEST_ERR_TROPIC_SENSORS_ERASE = 20099,
+ PRODTEST_ERR_TROPIC_SENSORS_READ_CONFIG = 20100,
+ PRODTEST_ERR_TROPIC_SENSORS_SLOT_READ = 20101,
+ PRODTEST_ERR_TROPIC_SENSORS_SLOT_WRITE = 20102,
+ PRODTEST_ERR_TROPIC_SENSORS_WRITE_VERIFY = 20103,
+ PRODTEST_ERR_TROPIC_READ_SENSORS_SESSION = 20104,
+ PRODTEST_ERR_TROPIC_READ_SENSORS_CONFIG = 20105,
+ PRODTEST_ERR_TROPIC_READ_CONFIGS_SESSION = 20106,
+ PRODTEST_ERR_TROPIC_READ_CONFIGS_R_CONFIG = 20107,
+ PRODTEST_ERR_TROPIC_READ_CONFIGS_I_CONFIG = 20108,
+ PRODTEST_ERR_TROPIC_BENCHMARK_NO_PAIRING_KEY = 20109,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MEM_ERASE = 20110,
+ PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_INVALIDATE = 20111,
+ PRODTEST_ERR_TROPIC_BENCHMARK_SESSION_START = 20112,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MAC_AND_DESTROY = 20113,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MEM_WRITE = 20114,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MEM_READ = 20115,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_INIT = 20116,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_GET = 20117,
+ PRODTEST_ERR_TROPIC_BENCHMARK_MCOUNTER_UPDATE = 20118,
+ PRODTEST_ERR_TROPIC_BENCHMARK_RANDOM_GET = 20119,
+
+ // === unit-test (21000–21999) ===
+ PRODTEST_ERR_UNIT_TEST_FAILED = 21010,
+
+ // === wpc (22000–22999) ===
+ PRODTEST_ERR_WPC_INFO_INIT = 22010,
+ PRODTEST_ERR_WPC_INFO_READ = 22011,
+ PRODTEST_ERR_WPC_BUF_SMALL = 22012,
+ PRODTEST_ERR_WPC_INFO_PM_REINIT = 22013,
+ PRODTEST_ERR_WPC_UPDATE_INIT = 22014,
+ PRODTEST_ERR_WPC_UPDATE_INFO_READ = 22015,
+ PRODTEST_ERR_WPC_UNKNOWN_CHIP_REVISION = 22016,
+ PRODTEST_ERR_WPC_UPDATE = 22017,
+ PRODTEST_ERR_WPC_UPDATE_PM_REINIT = 22018,
+
+ // === common — shared cert-chain and binary-update helpers (23000–23999) ===
+ PRODTEST_ERR_COMMON_CERT_EXTENSIONS = 23010,
+ PRODTEST_ERR_COMMON_CERT_AUTH_KEY_NOT_FOUND = 23011,
+ PRODTEST_ERR_COMMON_CERT_AUTH_KEY_EXTNVALUE = 23012,
+ PRODTEST_ERR_COMMON_CERT_AUTH_KEY_FIELD = 23013,
+ PRODTEST_ERR_COMMON_CERT_AUTH_KEY_LEN = 23014,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_CERT = 23015,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS = 23016,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS_PRELUDE = 23017,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SUBJECT = 23018,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_COMMON_NAME = 23019,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_DEVICE_SN = 23020,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_SERIAL_NUM = 23021,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_SN_MISMATCH = 23022,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SPKI = 23023,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_ALGORITHM = 23024,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_PUBKEY_BITS = 23025,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_PUBKEY = 23026,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_VERIFY_SIG = 23027,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SIG_ALG = 23028,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_SIG_VALUE = 23029,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_DER = 23030,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_ROOT = 23031,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_KEY = 23032,
+ PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_SIG = 23033,
+ PRODTEST_ERR_COMMON_UPDATE_NOT_STARTED = 23034,
+ PRODTEST_ERR_COMMON_UPDATE_NO_DATA = 23035,
+ PRODTEST_ERR_COMMON_UPDATE_FINALIZE = 23036,
+ PRODTEST_ERR_COMMON_UPDATE_UNKNOWN_PHASE = 23037,
+
+ // === prodtest (24000–24999) ===
+ PRODTEST_ERR_PRODTEST_WIPE_BLE_BONDS_ERASE = 24010,
+
+ // === syslog (25000–25999) ===
+ PRODTEST_ERR_SYSLOG_FILTER_SET = 25010,
+
+} prodtest_error_t;
diff --git a/core/embed/rtl/cli.c b/core/embed/rtl/cli.c
index e0d99432..a2ff37c0 100644
--- a/core/embed/rtl/cli.c
+++ b/core/embed/rtl/cli.c
@@ -158,8 +158,7 @@ void cli_ok_hexdata(cli_t* cli, const void* data, size_t size) {
cli->final_status = true;
}
-static void cli_verror(cli_t* cli, const char* code, const char* format,
- va_list args) {
+static void cli_verror(cli_t* cli, int code, const char* format, va_list args) {
if (cli->interactive) {
cli_printf(cli, ESC_COLOR_RED);
}
@@ -170,7 +169,7 @@ static void cli_verror(cli_t* cli, const char* code, const char* format,
cli_printf(cli, ESC_COLOR_RESET);
}
- cli_printf(cli, " %s", code);
+ cli_printf(cli, " %d", code);
if (format != NULL && format[0] != '\0') {
cli_printf(cli, " \"");
@@ -184,7 +183,7 @@ static void cli_verror(cli_t* cli, const char* code, const char* format,
cli->final_status = true;
}
-void cli_error(cli_t* cli, const char* code, const char* format, ...) {
+void cli_error(cli_t* cli, int code, const char* format, ...) {
va_list args;
va_start(args, format);
cli_verror(cli, code, format, args);
diff --git a/core/embed/rtl/inc/rtl/cli.h b/core/embed/rtl/inc/rtl/cli.h
index aab402ec..e6dff0e7 100644
--- a/core/embed/rtl/inc/rtl/cli.h
+++ b/core/embed/rtl/inc/rtl/cli.h
@@ -38,16 +38,14 @@ typedef struct cli cli_t;
/** Depth of the history buffer */
#define CLI_HISTORY_DEPTH 5
-/** Error codes */
-#define CLI_ERROR "error" /**< unspecified error */
-#define CLI_ERROR_INVALID_CMD "invalid-cmd"
-#define CLI_ERROR_INVALID_ARG "invalid-arg"
-#define CLI_ERROR_ABORT "abort"
-#define CLI_ERROR_FATAL "fatal"
-#define CLI_ERROR_TIMEOUT "timeout"
-#define CLI_ERROR_LOCKED "locked"
-#define CLI_ERROR_NODATA "no-data"
-#define CLI_ERROR_INVALID_CRC "invalid-crc"
+/** Framework-level error codes used internally by the CLI engine.
+ * Command handlers must use prodtest_error_t codes from
+ * prodtest_error_codes.h instead of these. */
+#define CLI_ERROR_INVALID_CMD 10
+#define CLI_ERROR_INVALID_ARG 11
+#define CLI_ERROR_ABORT 12
+#define CLI_ERROR_FATAL 13
+#define CLI_ERROR_INVALID_CRC 14
/** CLI command handler routine prototype */
typedef void (*cli_cmd_handler_t)(cli_t* cli);
@@ -232,7 +230,7 @@ void cli_progress(cli_t* cli, const char* format, ...);
* automatically prefixed with the "ERROR" string and terminated with CR/LF
* characters.
*/
-void cli_error(cli_t* cli, const char* code, const char* format, ...);
+void cli_error(cli_t* cli, int code, const char* format, ...);
/**
* Writes an invalid argument error message to the console
diff --git a/core/embed/sys/dbg/syslog.c b/core/embed/sys/dbg/syslog.c
index a42b57b7..49fa7415 100644
--- a/core/embed/sys/dbg/syslog.c
+++ b/core/embed/sys/dbg/syslog.c
@@ -271,6 +271,8 @@ void syslog_tsh_error(ts_t status, const char* file, int line) {
#include <rtl/cli.h>
+#include "prodtest_error_codes.h"
+
static void prodtest_set_log_filter(cli_t* cli) {
const char* filter = cli_arg(cli, "filter");
size_t filter_len = strlen(filter);
@@ -286,7 +288,7 @@ static void prodtest_set_log_filter(cli_t* cli) {
}
if (!syslog_set_filter(filter, filter_len)) {
- cli_error(cli, CLI_ERROR, "Failed to set log filter.");
+ cli_error(cli, PRODTEST_ERR_SYSLOG_FILTER_SET, "Failed to set log filter.");
}
cli_ok(cli, "");
diff --git a/core/tools/prodtest_error_codes.py b/core/tools/prodtest_error_codes.py
new file mode 100644
index 00000000..71b83083
--- /dev/null
+++ b/core/tools/prodtest_error_codes.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python3
+"""
+Parse prodtest_error_codes.h and emit a JSON error code table.
+
+The JSON is intended for host-side tooling that needs to map numeric error
+codes received over the prodtest CLI back to human-readable names and modules.
+
+Usage:
+ prodtest_error_codes.py # write to the default path
+ prodtest_error_codes.py -o errors.json # write to a different file
+ prodtest_error_codes.py --stdout # print JSON to stdout
+ prodtest_error_codes.py --check # verify the file is up to date
+ prodtest_error_codes.py --header path/to/prodtest_error_codes.h
+"""
+
+import argparse
+import json
+import re
+import sys
+from pathlib import Path
+
+TOOLS_DIR = Path(__file__).parent
+CORE_DIR = TOOLS_DIR.parent
+
+DEFAULT_HEADER = CORE_DIR / "embed/projects/prodtest/prodtest_error_codes.h"
+DEFAULT_CLI_HEADER = CORE_DIR / "embed/rtl/inc/rtl/cli.h"
+DEFAULT_VERSION_HEADER = CORE_DIR / "embed/projects/prodtest/version.h"
+DEFAULT_OUTPUT = CORE_DIR / "embed/projects/prodtest/error_codes.json"
+
+# Matches: // === backup-ram (1000–1999) ===
+# or: // === otp — some note (10000–10999) ===
+_MODULE_RE = re.compile(r"//\s*===\s*(.+?)\s*\((\d+)\s*[–-]\s*(\d+)\)\s*")
+
+# Matches: PRODTEST_ERR_FOO_BAR = 1234,
+_ENUM_RE = re.compile(r"^\s*(PRODTEST_ERR_\w+)\s*=\s*(\d+)\s*,?")
+
+# Matches: #define CLI_ERROR_INVALID_CMD 1
+_CLI_DEFINE_RE = re.compile(r"^\s*#define\s+(CLI_ERROR_\w+)\s+(\d+)")
+
+# Matches: #define VERSION_MAJOR 0
+_VERSION_DEFINE_RE = re.compile(
+ r"^\s*#define\s+(VERSION_MAJOR|VERSION_MINOR|VERSION_PATCH|VERSION_BUILD)\s+(\d+)"
+)
+
+
+def parse_prodtest_header(path: Path) -> tuple[list[dict], list[dict]]:
+ """Return (modules, errors) parsed from prodtest_error_codes.h."""
+ modules: list[dict] = []
+ errors: list[dict] = []
+ current_module: str | None = None
+
+ for line in path.read_text(encoding="utf-8").splitlines():
+ m = _MODULE_RE.search(line)
+ if m:
+ # Extract the module name, stripping any trailing note after " — "
+ raw_name = m.group(1).strip()
+ name = raw_name.split(" — ")[0].strip()
+ range_start = int(m.group(2))
+ range_end = int(m.group(3))
+ current_module = name
+ modules.append(
+ {"module": name, "range_start": range_start, "range_end": range_end}
+ )
+ continue
+
+ m = _ENUM_RE.match(line)
+ if m:
+ errors.append(
+ {
+ "code": int(m.group(2)),
+ "name": m.group(1),
+ "module": current_module,
+ }
+ )
+
+ return modules, errors
+
+
+def parse_cli_header(path: Path) -> list[dict]:
+ """Return framework-level error codes from cli.h."""
+ codes = []
+ for line in path.read_text(encoding="utf-8").splitlines():
+ m = _CLI_DEFINE_RE.match(line)
+ if m:
+ codes.append({"code": int(m.group(2)), "name": m.group(1)})
+ return sorted(codes, key=lambda c: c["code"])
+
+
+def parse_version_header(path: Path) -> str:
+ """Return the prodtest version string from version.h as 'MAJOR.MINOR.PATCH.BUILD'."""
+ parts: dict[str, int] = {}
+ for line in path.read_text(encoding="utf-8").splitlines():
+ m = _VERSION_DEFINE_RE.match(line)
+ if m:
+ parts[m.group(1)] = int(m.group(2))
+ missing = [
+ k
+ for k in ("VERSION_MAJOR", "VERSION_MINOR", "VERSION_PATCH", "VERSION_BUILD")
+ if k not in parts
+ ]
+ if missing:
+ raise ValueError(f"{path}: missing {', '.join(missing)}")
+ return (
+ f"{parts['VERSION_MAJOR']}.{parts['VERSION_MINOR']}."
+ f"{parts['VERSION_PATCH']}.{parts['VERSION_BUILD']}"
+ )
+
+
+def build_output(
+ modules: list[dict],
+ errors: list[dict],
+ framework_codes: list[dict],
+ header_path: Path,
+ version: str,
+) -> dict:
+ return {
+ "source": header_path.name,
+ "prodtest_version": version,
+ "framework_codes": framework_codes,
+ "modules": modules,
+ "errors": errors,
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
+ )
+ parser.add_argument(
+ "--header",
+ type=Path,
+ default=DEFAULT_HEADER,
+ help=f"Path to prodtest_error_codes.h (default: {DEFAULT_HEADER})",
+ )
+ parser.add_argument(
+ "--cli-header",
+ type=Path,
+ default=DEFAULT_CLI_HEADER,
+ help=f"Path to cli.h for framework codes (default: {DEFAULT_CLI_HEADER})",
+ )
+ parser.add_argument(
+ "--version-header",
+ type=Path,
+ default=DEFAULT_VERSION_HEADER,
+ help=f"Path to prodtest version.h (default: {DEFAULT_VERSION_HEADER})",
+ )
+ parser.add_argument(
+ "-o",
+ "--output",
+ type=Path,
+ default=DEFAULT_OUTPUT,
+ help=f"Output file path (default: {DEFAULT_OUTPUT})",
+ )
+ parser.add_argument(
+ "--stdout",
+ action="store_true",
+ help="Print JSON to stdout instead of writing to a file",
+ )
+ parser.add_argument(
+ "--check",
+ action="store_true",
+ help="Exit non-zero if the output file is missing or out of date",
+ )
+ parser.add_argument(
+ "--indent",
+ type=int,
+ default=2,
+ help="JSON indentation (default: 2)",
+ )
+ args = parser.parse_args()
+
+ if not args.header.exists():
+ print(f"error: header not found: {args.header}", file=sys.stderr)
+ sys.exit(1)
+
+ modules, errors = parse_prodtest_header(args.header)
+
+ framework_codes: list[dict] = []
+ if args.cli_header.exists():
+ framework_codes = parse_cli_header(args.cli_header)
+
+ if not args.version_header.exists():
+ print(
+ f"error: version header not found: {args.version_header}", file=sys.stderr
+ )
+ sys.exit(1)
+ version = parse_version_header(args.version_header)
+
+ result = build_output(modules, errors, framework_codes, args.header, version)
+ json_str = json.dumps(result, indent=args.indent) + "\n"
+
+ if args.check:
+ if not args.output.exists():
+ print(f"error: {args.output} does not exist", file=sys.stderr)
+ sys.exit(1)
+ current = args.output.read_text(encoding="utf-8")
+ if current != json_str:
+ print(
+ f"error: {args.output} is out of date — re-run"
+ f" {Path(__file__).name} to regenerate",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ return
+
+ if args.stdout:
+ sys.stdout.write(json_str)
+ else:
+ args.output.write_text(json_str, encoding="utf-8")
+ print(
+ f"wrote {len(errors)} error codes across {len(modules)} modules"
+ f" to {args.output}",
+ file=sys.stderr,
+ )
+
+
+if __name__ == "__main__":
+ main()
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.