Safe Data API
CRC-protected (optionally redundant) data containers for Zephyr
v0.0-dev+gbb519af
Loading...
Searching...
No Matches
Containers and Typed Access

Typed container definition and access macros - the primary API. More...

Macros

#define SAFE_CONTAINER_DEFINE(_container_name, _payload_type)
 Declare a CRC-protected container type wrapping _payload_type.
#define SAFE_CONTAINER_DEFINE_UNCHECKED(_container_name, _payload_type)
 As SAFE_CONTAINER_DEFINE but without the tag-strength size bound. For documented deviations only.
#define SAFE_INIT(_c)
 Initialise and seal a container.
#define SAFE_VERIFY(_c)
 Verify integrity only (pure, never modifies the payload).
#define SAFE_READ(_c, _out_ptr)
 Validated copy out into _out_ptr.
#define SAFE_WRITE(_c, _in_ptr)
 Validated copy in from _in_ptr + reseal.
#define SAFE_UPDATE(_c, _fn, _user)
 Atomic read-modify-write via callback.
#define SAFE_COMMIT(_c)
 Reseal after an explicit external modification.
#define SAFE_SECTION(_c, _pvar)
 Scoped lock + verify ... reseal + unlock around a block.

Detailed Description

Typed container definition and access macros - the primary API.

Declare a container type with SAFE_CONTAINER_DEFINE(), then access it exclusively through the SAFE_* operations; they derive the type-erased arguments at compile time and forward to Type-Erased Core.

Macro Definition Documentation

◆ SAFE_COMMIT

#define SAFE_COMMIT ( _c)
Value:
safe_data_commit(_SAFE_LOCK(_c), &(_c)->payload, \
sizeof((_c)->payload), &(_c)->_crc, _SAFE_SHADOW(_c))
int safe_data_commit(struct k_mutex *lock, void *payload, size_t len, uint32_t *crc, void *shadow)
Reseal after an explicit external modification (advanced use). Lock, recompute the integrity tag,...
Definition safe_data.c:454

Reseal after an explicit external modification.

See also
safe_data_commit
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
Returns
As safe_data_commit().
Depends on
defined(CONFIG_SAFE_DATA_ALLOW_UNCHECKED_COMMIT)

Definition at line 616 of file safe_data.h.

Satisfies requirement SD-REQ-020 (Reduced API surface at the Strict level).

◆ SAFE_CONTAINER_DEFINE

#define SAFE_CONTAINER_DEFINE ( _container_name,
_payload_type )
Value:
struct _container_name { \
BUILD_ASSERT(sizeof(_payload_type) > 0, \
"safe_data: zero-size payload"); \
BUILD_ASSERT(sizeof(_payload_type) <= Z_SAFE_DATA_MAX_PAYLOAD, \
"safe_data: payload too large for the configured" \
" integrity tag (see Z_SAFE_DATA_MAX_PAYLOAD)"); \
Z_SAFE_CONTAINER_BODY(_payload_type) \
}

Declare a CRC-protected container type wrapping _payload_type.

Generates a struct with an optional mutex (only when CONFIG_SAFE_DATA_LOCKING, the default), an integrity tag, an optional redundant shadow copy (only when CONFIG_SAFE_DATA_REDUNDANT), and the user payload.

Rejects zero-size payloads and payloads exceeding the size bound of the configured tag (CRC-8: 16 bytes, CRC-16: 256 bytes) at compile time.

Usage:

SAFE_CONTAINER_DEFINE(safe_config, struct system_config);
static struct safe_config cfg;
#define SAFE_CONTAINER_DEFINE(_container_name, _payload_type)
Declare a CRC-protected container type wrapping _payload_type.
Definition safe_data.h:523
Parameters
_container_nameName of the generated struct type.
_payload_typeComplete type of the protected payload.

Definition at line 523 of file safe_data.h.

Satisfies requirement SD-REQ-019 (Compile-time payload guards).

◆ SAFE_CONTAINER_DEFINE_UNCHECKED

#define SAFE_CONTAINER_DEFINE_UNCHECKED ( _container_name,
_payload_type )
Value:
struct _container_name { \
BUILD_ASSERT(sizeof(_payload_type) > 0, \
"safe_data: zero-size payload"); \
Z_SAFE_CONTAINER_BODY(_payload_type) \
}

As SAFE_CONTAINER_DEFINE but without the tag-strength size bound. For documented deviations only.

Parameters
_container_nameName of the generated struct type.
_payload_typeComplete type of the protected payload.

Definition at line 540 of file safe_data.h.

◆ SAFE_INIT

#define SAFE_INIT ( _c)
Value:
safe_data_init(_SAFE_LOCK(_c), &(_c)->payload, sizeof((_c)->payload), \
&(_c)->_crc, _SAFE_SHADOW(_c))
int safe_data_init(struct k_mutex *lock, void *payload, size_t len, uint32_t *crc, void *shadow)
Initialise the lock and seal the current payload contents.
Definition safe_data.c:224

Initialise and seal a container.

See also
safe_data_init
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
Returns
As safe_data_init().

Definition at line 562 of file safe_data.h.

◆ SAFE_READ

#define SAFE_READ ( _c,
_out_ptr )
Value:
safe_data_read(_SAFE_LOCK(_c), &(_c)->payload, sizeof((_c)->payload), \
&(_c)->_crc, _SAFE_SHADOW(_c), (_out_ptr))
int safe_data_read(struct k_mutex *lock, void *payload, size_t len, uint32_t *crc, void *shadow, void *out)
Verify under lock and copy the payload out to out.
Definition safe_data.c:326

Validated copy out into _out_ptr.

See also
safe_data_read
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
_out_ptrDestination buffer of at least sizeof(payload) bytes.
Returns
As safe_data_read().

Definition at line 582 of file safe_data.h.

◆ SAFE_SECTION

#define SAFE_SECTION ( _c,
_pvar )
Value:
for (int _sd_st = ((z_safe_lock(_SAFE_LOCK(_c)) == 0) \
sizeof((_c)->payload), (_c)->_crc, \
_SAFE_SHADOW(_c)) \
: (z_safe_data_lock_failed(), -ETIMEDOUT)); \
/* enter on valid (0) or recovered (-EAGAIN) */ \
({ bool _ok = (_sd_st == 0 || _sd_st == SAFE_DATA_RECOVERED); \
if (!_ok && _sd_st != -ETIMEDOUT) { \
z_safe_unlock(_SAFE_LOCK(_c)); \
} \
_ok; }); \
z_safe_data_seal(&(_c)->payload, sizeof((_c)->payload), \
&(_c)->_crc, _SAFE_SHADOW(_c)), \
z_safe_unlock(_SAFE_LOCK(_c)), _sd_st = 1) \
for (__typeof__((_c)->payload) *_pvar = &(_c)->payload; \
_pvar != NULL; _pvar = NULL)
int safe_data_verify_repair(void *payload, size_t len, uint32_t crc, void *shadow)
Verify payload integrity and repair a recoverable fault in place.
Definition safe_data.c:290
#define SAFE_DATA_RECOVERED
Return code for a fault that the redundant shadow copy covers.
Definition safe_data.h:83

Scoped lock + verify ... reseal + unlock around a block.

Inside the block, _pvar is a typed pointer to the (verified) payload and may be used with plain C syntax. On normal exit the integrity tag is resealed and the lock released. This is the ergonomic, leak-free replacement for the original "checkout pointer / remember to update" pattern.

The block is entered only if the pre-check passes (or the data was recovered from the shadow copy). On an unrecoverable fault the block is skipped and the lock is released; the configured fault action has already run inside safe_data_verify().

SAFE_SECTION(&cfg, p) {
p->temperature = 90;
p->fan_enabled = (p->temperature > 85);
}
#define SAFE_SECTION(_c, _pvar)
Scoped lock + verify ... reseal + unlock around a block.
Definition safe_data.h:663
Note
Do not return/break/goto out of the block: that would skip the reseal+unlock. continue is fine (it exits the block normally).
Uses GNU C extensions (statement expressions, typeof) and hides control flow in a macro - only available with CONFIG_SAFE_DATA_GNU_EXTENSIONS (off at the Strict level). SAFE_UPDATE gives the same atomicity guarantee in standard C.

The block is also skipped (and the lock-timeout event reported) when the container lock cannot be acquired within CONFIG_SAFE_DATA_LOCK_TIMEOUT_MS.

Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
_pvarName of the typed payload-pointer variable scoped to the block.
Depends on
defined(CONFIG_SAFE_DATA_GNU_EXTENSIONS)

Definition at line 663 of file safe_data.h.

Satisfies requirements SD-REQ-014 (Bounded lock acquisition), SD-REQ-015 (No ISR-context locking), SD-REQ-016 (Serialised access — no torn snapshots), SD-REQ-020 (Reduced API surface at the Strict level), and SD-REQ-021 (Scoped access block).

◆ SAFE_UPDATE

#define SAFE_UPDATE ( _c,
_fn,
_user )
Value:
safe_data_update(_SAFE_LOCK(_c), &(_c)->payload, sizeof((_c)->payload),\
&(_c)->_crc, _SAFE_SHADOW(_c), (_fn), (_user))
int safe_data_update(struct k_mutex *lock, void *payload, size_t len, uint32_t *crc, void *shadow, safe_data_mutator_t fn, void *user)
Atomic read-modify-write: lock, verify, run fn, reseal on success.
Definition safe_data.c:386

Atomic read-modify-write via callback.

See also
safe_data_update
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
_fnMutator of type safe_data_mutator_t.
_userOpaque context forwarded to _fn.
Returns
As safe_data_update().

Definition at line 603 of file safe_data.h.

◆ SAFE_VERIFY

#define SAFE_VERIFY ( _c)
Value:
safe_data_verify(&(_c)->payload, sizeof((_c)->payload), (_c)->_crc, \
_SAFE_SHADOW(_c))
int safe_data_verify(const void *payload, size_t len, uint32_t crc, const void *shadow)
Verify payload integrity. Pure: read-only and lock-free; it NEVER modifies the payload,...
Definition safe_data.c:277

Verify integrity only (pure, never modifies the payload).

See also
safe_data_verify
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
Returns
As safe_data_verify().

Definition at line 572 of file safe_data.h.

◆ SAFE_WRITE

#define SAFE_WRITE ( _c,
_in_ptr )
Value:
safe_data_write(_SAFE_LOCK(_c), &(_c)->payload, sizeof((_c)->payload), \
&(_c)->_crc, _SAFE_SHADOW(_c), (_in_ptr))
int safe_data_write(struct k_mutex *lock, void *payload, size_t len, uint32_t *crc, void *shadow, const void *in)
Copy in into the payload under lock and reseal the integrity tag.
Definition safe_data.c:354

Validated copy in from _in_ptr + reseal.

See also
safe_data_write
Parameters
_cPointer to a container declared with SAFE_CONTAINER_DEFINE().
_in_ptrSource buffer of at least sizeof(payload) bytes.
Returns
As safe_data_write().

Definition at line 592 of file safe_data.h.