What changed, and why it matters
This commit is a routine internal refactoring of how the Trezor firmware represents success/error status codes. It introduces a new typed status code (ts_t), helper macros to check it, and a function to convert HAL driver errors into these new codes. There is no change to user-facing behavior, no bug fix, and no security patch.
No security action required; review as normal code-quality change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds a ts_t status-code abstraction in core/embed/rtl/inc/rtl/error_handling.h, mapping standard errno values (EINVAL, ENOMEM, ENOENT, EBUSY, ETIMEDOUT, EIO, EBADMSG) to named constants, plus ts_ok/ts_error/ts_eq/ts_string helpers and ensure_ok/ensure_true/ensure macros. It also adds a static inline hal_status_to_ts() converter in trezor_bsp.h for STM32 HAL status codes. The existing error_shutdown/__fatal_error/__stack_chk_fail functions are preserved unchanged. No call sites are modified and no vulnerability is addressed.
Changed components
core/embed/rtl/error_handling.ccore/embed/rtl/inc/rtl/error_handling.hcore/embed/sys/bsp/inc/trezor_bsp.hInspect captured patch +186 / −14
diff --git a/core/embed/rtl/error_handling.c b/core/embed/rtl/error_handling.c
index 33145dff8..23fc32e9c 100644
--- a/core/embed/rtl/error_handling.c
+++ b/core/embed/rtl/error_handling.c
@@ -34,6 +34,28 @@ void __attribute__((noreturn, used)) __stack_chk_fail(void) {
error_shutdown("(SS)");
}
+const char *ts_string(ts_t status) {
+ if (ts_eq(status, TS_OK)) {
+ return "OK";
+ } else if (ts_eq(status, TS_EINVAL)) {
+ return "EINVAL";
+ } else if (ts_eq(status, TS_ENOMEM)) {
+ return "ENOMEM";
+ } else if (ts_eq(status, TS_ENOENT)) {
+ return "ENOENT";
+ } else if (ts_eq(status, TS_EBUSY)) {
+ return "EBUSY";
+ } else if (ts_eq(status, TS_ETIMEDOUT)) {
+ return "ETIMEDOUT";
+ } else if (ts_eq(status, TS_EIO)) {
+ return "EIO";
+ } else if (ts_eq(status, TS_EBADMSG)) {
+ return "EBADMSG";
+ } else {
+ return "?ERROR";
+ }
+}
+
void __attribute__((noreturn))
error_shutdown_ex(const char *title, const char *message, const char *footer) {
system_exit_error(title, message, footer);
diff --git a/core/embed/rtl/inc/rtl/error_handling.h b/core/embed/rtl/inc/rtl/error_handling.h
index ce451dd08..3b2f3771c 100644
--- a/core/embed/rtl/inc/rtl/error_handling.h
+++ b/core/embed/rtl/inc/rtl/error_handling.h
@@ -19,21 +19,157 @@
#pragma once
-#include <sys/bootutils.h>
+#include <errno.h>
-// Shows an error message and shuts down the device.
-//
-// If the title is NULL, it will be set to "INTERNAL ERROR".
-// If the message is NULL, it will be ignored.
-// If the footer is NULL, it will be set to "PLEASE VISIT TREZOR.IO/RSOD".
+// Suppresses the intellisense error in VSCode
+#ifndef __FILE_NAME__
+#define __FILE_NAME__ __FILE__
+#endif
+
+/** Status code type */
+typedef struct {
+ // Do not access this field directly,
+ // use `ts_ok()` and `ts_error()` macros.
+ int code;
+} ts_t;
+
+/** OK status code (signalling success or no error) */
+#define TS_OK ts_make(0)
+
+#define TS_EINVAL ts_make(EINVAL)
+#define TS_ENOMEM ts_make(ENOMEM)
+#define TS_ENOENT ts_make(ENOENT)
+#define TS_EBUSY ts_make(EBUSY)
+#define TS_ETIMEDOUT ts_make(ETIMEDOUT)
+#define TS_EIO ts_make(EIO)
+#define TS_EBADMSG ts_make(EBADMSG)
+
+// #define TS_SPECIFIC_BASE 1000
+// #define TS_ERROR ts_make(TS_SPECIFIC_BASE + 0) // Generic error
+
+/**
+ * Extracts the code integer value from status structure.
+ *
+ * @param status Status structure
+ * @return Integer status code
+ */
+#define ts_code(status) ((status).code)
+
+/**
+ * Converts integer to status structure.
+ *
+ * @param value Integer status code
+ * @return Status structure
+ */
+#define ts_make(value) ((const ts_t){(value)})
+
+/**
+ * Check if status code is `TS_OK`.
+ *
+ * @param status Status structure
+ * @return true if status is OK
+ */
+#define ts_ok(status) (ts_code(status) == ts_code(TS_OK))
+
+/**
+ * Checks if status code is not `TS_OK`.
+ *
+ * @param status Status structure
+ * @return true if status is an error
+ */
+#define ts_error(status) (ts_code(status) != ts_code(TS_OK))
+
+/**
+ * Checks if both status codes are equal.
+ *
+ * @param status1 First status structure
+ * @param status2 Second status structure
+ * @return true if both status codes are equal
+ */
+#define ts_eq(status1, status2) (ts_code(status1) == ts_code(status2))
+
+/**
+ * Returns a string representation of the status code.
+ *
+ * TS_OK -> "OK"
+ * TS_Exxx -> "Exxx"
+ *
+ * @param status Status structure
+ * @return String representation of the status code
+ */
+const char *ts_string(ts_t status);
+
+/**
+ * Ensures that status code is `TS_OK`. If not, it shows an error message
+ * and shuts down the device.
+ *
+ * @param status Status structure
+ * @param msg Error message to show if status is not OK
+ */
+#define ensure_ok(status, msg) \
+ do { \
+ if (!ts_ok(status)) { \
+ __fatal_error(msg, __FILE_NAME__, __LINE__); \
+ } \
+ } while (0)
+
+/**
+ * Ensures that condition is evaluated as `true`. If not, it shows
+ * an error message and shuts down the device.
+ *
+ * @param cond Condition to check
+ * @param msg Error message to show if condition is not true
+ */
+#define ensure_true(cond, msg) \
+ do { \
+ if (!(cond)) { \
+ __fatal_error(msg, __FILE_NAME__, __LINE__); \
+ } \
+ } while (0)
+
+/**
+ * Ensures that condition is evaluated as `sectrue`. If not, it shows
+ * an error message and shuts down the device.
+ *
+ * @param seccond Security condition to check
+ * @param msg Error message to show if condition is not sectrue
+ */
+#define ensure(seccond, msg) \
+ do { \
+ if ((seccond) != sectrue) { \
+ __fatal_error(msg, __FILE_NAME__, __LINE__); \
+ } \
+ } while (0)
+
+/**
+ * Shows an error message and shuts down the device.
+ *
+ * @param title Title of the error message (defaults to
+ * "INTERNAL ERROR" if NULL)
+ * @param message Main error message (defaults to no message if NULL)
+ * @param footer Footer of the error message (defaults to
+ * "PLEASE VISIT TREZOR.IO/RSOD" if NULL)
+ */
void __attribute__((noreturn))
error_shutdown_ex(const char *title, const char *message, const char *footer);
-// Shows an error message and shuts down the device.
-//
-// Same as `error_shutdown_ex()` but with a default header and footer.
+/**
+ * Shows an error message and shuts down the device.
+ *
+ * @param message Main error message (defaults to no message if NULL)
+ */
void __attribute__((noreturn)) error_shutdown(const char *message);
-// Do not use this function directly, use the `ensure()` macro instead.
+/**
+ * Shows a fatal error message with file and line information,
+ * and shuts down the device.
+ *
+ * Do not use this function directly, use the `ensure_xxx() or
+ * assert() macros instead.
+ *
+ * @param msg Error message
+ * @param file Source file name where the error occurred
+ * @param line Line number in the source file where the error occurred
+ */
void __attribute__((noreturn))
__fatal_error(const char *msg, const char *file, int line);
diff --git a/core/embed/sys/bsp/inc/trezor_bsp.h b/core/embed/sys/bsp/inc/trezor_bsp.h
index d2e220c79..cb04758d5 100644
--- a/core/embed/sys/bsp/inc/trezor_bsp.h
+++ b/core/embed/sys/bsp/inc/trezor_bsp.h
@@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZOR_BSP_H
-#define TREZOR_BSP_H
+#pragma once
// Trezor 'board support package' (BSP) header file that includes
// all necessary headers for the specific board including STM32 HAL and
@@ -27,10 +26,25 @@
// This file should be only included by driver implementations and
// should not be included by application code.
+#include <rtl/error_handling.h>
+
#include TREZOR_BOARD
#ifndef TREZOR_EMULATOR
#include STM32_HAL_H
-#endif
-#endif // TREZOR_BOARD_H
+// HAL status code helpers
+static inline ts_t hal_status_to_ts(HAL_StatusTypeDef hal_status) {
+ switch (hal_status) {
+ case HAL_OK:
+ return TS_OK;
+ case HAL_BUSY:
+ return TS_EBUSY;
+ case HAL_TIMEOUT:
+ return TS_ETIMEDOUT;
+ default:
+ return TS_EIO;
+ }
+}
+
+#endif
Why this scored 15/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.