<alp/storage.h> — Block Storage
Generic block storage over flash, eMMC, or SD. Optional inline AES encryption on AEN SecAES targets.
:::danger Breaking change — writes need allow_unsafe_write on Yocto/Linux
alp_storage_config_t now carries bool allow_unsafe_write, defaulting to false. On the Yocto/Linux backend, alp_storage_write() and alp_storage_erase() return ALP_ERR_INVAL unless it is set true.
This is a data-destruction guard, not a formality. On this backend /dev/mmcblk<N> is the whole-disk node — not a partition — and on V2N /dev/mtd0 is the FIP/bootloader partition. An unguarded write to either bricks the board. Reads are unaffected.
:::
Header
#include <alp/storage.h>
Read / write a block
alp_storage_t *st = alp_storage_open(&(alp_storage_config_t){
.device = ALP_STORAGE_DEVICE_OSPI_FLASH,
});
uint8_t block[256];
alp_storage_read(st, /* offset */ 0x1000, block, sizeof(block));
alp_storage_write(st, 0x1000, block, sizeof(block));
alp_storage_close(st);
allow_unsafe_write — the destructive-write guard
| Field | Type | Default | Notes |
|---|---|---|---|
allow_unsafe_write | bool | false | Yocto/Linux backend: alp_storage_write() and alp_storage_erase() return ALP_ERR_INVAL unless true. |
alp_storage_config_t cfg = ALP_STORAGE_CONFIG_DEFAULT(ALP_STORAGE_KIND_SD_MMC);
cfg.allow_unsafe_write = true; // I accept that this node is the whole disk
The device nodes this backend opens are not partitions:
ALP_STORAGE_KIND_SD_MMC→/dev/mmcblk<N>, the whole-disk node. A write at offset 0 lands on the partition table.- On V2N,
/dev/mtd0is the FIP/bootloader partition. Writing or erasing it without knowing exactly what you are doing bricks the board.
There is no undo and no confirmation prompt on an embedded target, so the SDK requires the caller to opt in per handle. Leave it false for read-only workloads.
Yocto / Linux (V2N / V2M) backend
alp_storage_open(), alp_storage_read() and alp_storage_get_info() are now real on this backend; they previously returned ALP_ERR_NOSUPPORT.
| Kind | Node | Geometry source |
|---|---|---|
ALP_STORAGE_KIND_SD_MMC | /dev/mmcblk<N> | BLKGETSIZE64 / BLKSSZGET |
INTERNAL_FLASH / QSPI_FLASH / OSPI_FLASH | /dev/mtd<N> | MEMGETINFO |
Geometry is read from the kernel, not assumed, and I/O is real pread / pwrite.
alp_storage_configure_inline_aes() remains ALP_ERR_NOSUPPORT on this backend.
Inline AES (AEN OSPI / HexSPI)
On AEN's OSPI / HexSPI controllers, inline AES decryption can be enabled at storage open time:
alp_storage_t *st = alp_storage_open(&(alp_storage_config_t){
.device = ALP_STORAGE_DEVICE_OSPI_FLASH,
});
alp_storage_inline_aes_t aes = {
.key_slot = 0,
.iv = { /* 16 bytes */ },
};
alp_storage_configure_inline_aes(st, &aes);
After this, reads return decrypted data transparently. Useful for protected firmware images and credential blobs.
File systems
For higher-level access, declare your partitions in board.yaml's storage: block — the orchestrator emits the fixed-partitions DTS overlay and the per-fs Kconfig (CONFIG_FILE_SYSTEM_LITTLEFS=y / _FAT_FILESYSTEM_ELM=y / _FILE_SYSTEM_EXT2=y) plus an optional static fs_mount_t alp_storage_mounts[] table for boot-time iteration.
Default-initialiser macro
ALP_STORAGE_CONFIG_DEFAULT(id) (v0.10) takes the backing-store kind as its identity argument:
alp_storage_config_t cfg = ALP_STORAGE_CONFIG_DEFAULT(ALP_STORAGE_KIND_INTERNAL_FLASH);
It sets kind from id plus: instance_id = 0, freq_hz = 0 (use the devicetree default), read_only = false, and allow_unsafe_write = false.
The allow_unsafe_write = false default is the point of the macro here: a config that picks up the new field automatically defaults to the non-destructive setting, so code written before the field existed cannot start erasing a bootloader by accident.
See the shared macro contract for the C++ compound-literal caveat that applies to every ALP_*_CONFIG_DEFAULT.