164 ((bs & (bs - 1U)) != 0U)) {
201 const uint32_t tot_sec = (tot_sec_16 != 0U) ? tot_sec_16 : tot_sec_32;
232 const uint32_t root_dir_sectors =
318 if (buf[type_off] == 0U) {
321 const uint32_t base =
priv_rd32(&buf[lba_off]);
404 if (backend ==
nullptr || opts ==
nullptr) {
407 if (backend->write_block ==
nullptr || backend->get_capacity ==
nullptr) {
408 return k_ra8_err_invalid_arg;
412 return k_ra8_err_not_supported;
415 return k_ra8_err_invalid_arg;
417 uint64_t block_count = 0U;
418 uint32_t block_size = 0U;
419 ra8_err_t err = backend->get_capacity(backend->ctx, &block_count, &block_size);
427 return priv_exfat_format(backend, block_count, block_size, opts->label);
430 geom.
type = opts->type;
431 geom.total_sectors = block_count;
432 geom.bytes_per_sector = block_size;
535 uint64_t dev_blocks = 0U;
536 uint32_t dev_bps = 0U;
562 if (backend ==
nullptr) {
565 if (out_type ==
nullptr) {
568 if (backend->read_block ==
nullptr) {
569 return k_ra8_err_invalid_arg;
571 if (backend->get_capacity ==
nullptr) {
572 return k_ra8_err_invalid_arg;
590 *out_type = probe.type;
631 if (backend ==
nullptr || out_handle ==
nullptr) {
634 if (backend->read_block ==
nullptr || backend->write_block ==
nullptr ||
635 backend->get_capacity ==
nullptr) {
636 return k_ra8_err_invalid_arg;
650 m->backend = *backend;
651 m->partition_base_lba = 0U;
662 m->exfat_upcase_ok = 0U;
720 if (handle ==
nullptr) {
723 if (handle->in_use == 0U) {
724 return k_ra8_err_invalid_state;
Annotation-attribute framework macros for ra8-firmware.
#define RA8_OWNS_RESOURCE(kind)
RAII-style resource ownership contract.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_EXPECTS_LOCK(name)
The function expects the named thread/IRQ lock to be held on entry.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_format(const ra8_fs_backend_t *backend, const ra8_fs_format_opts_t *opts)
Format a block device as a fresh, empty FAT12/FAT16/FAT32/exFAT volume.
ra8_err_t ra8_fs_mount(const ra8_fs_backend_t *backend, ra8_fs_mount_t **out_handle)
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
ra8_err_t ra8_fs_mount_partition(const ra8_fs_backend_t *backend, uint8_t index, ra8_fs_mount_t **out_handle)
Mount a FAT/exFAT volume from a specific partition of a block device.
ra8_err_t ra8_fs_unmount(ra8_fs_mount_t *handle)
Unmount a previously mounted volume and release its slot.
ra8_err_t ra8_fs_probe(const ra8_fs_backend_t *backend, ra8_fs_type_t *out_type)
Identify a FAT/exFAT volume without claiming a mount slot.
uint32_t priv_rd32(const uint8_t *p)
Decode a little-endian uint32_t from a byte buffer.
uint16_t priv_rd16(const uint8_t *p)
Decode a little-endian uint16_t from a byte buffer.
ra8_err_t priv_read_sector(const ra8_fs_mount_t *m, uint64_t lba, uint8_t *buf)
Read a single sector into the module scratch buffer.
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
ra8_err_t priv_fsinfo_seed(const ra8_fs_mount_t *m)
Validate FAT32's FSInfo sector and seed the hint and free count.
void priv_alloc_state_bind(const ra8_fs_mount_t *m)
Claim and reset the allocator state slot for a freshly mounted volume.
ra8_err_t priv_fsinfo_flush(const ra8_fs_mount_t *m)
Write the tracked free count and next-free hint back into FSInfo.
void priv_alloc_state_release(const ra8_fs_mount_t *m)
Release the allocator state slot held by m.
const uint8_t k_zero_sector[k_ra8_fs_sector_max]
One whole sector of zero bytes, in read-only storage.
ra8_err_t priv_parse_volume(ra8_fs_mount_t *m)
Parse the volume at the current base: exFAT first, then FAT BPB.
ra8_err_t priv_fmt_emit_volume(const ra8_fs_backend_t *backend, const ra8_fs_fmt_geom_t *g, const char *label)
Lay down the boot sector, FAT seeds, FSInfo, and the empty root.
ra8_err_t priv_fmt_choose_geometry(ra8_fs_fmt_geom_t *g, uint32_t spc_hint)
Pick the cluster size that lands the FAT cluster count in the right band.
bool priv_fmt_spc_valid(uint8_t spc)
Validate a caller-pinned sectors-per-cluster value.
uint32_t priv_fmt_reserved_for(ra8_fs_type_t type)
Map a requested FAT type to its reserved-sector count.
ra8_err_t priv_gpt_locate_volume(const ra8_fs_mount_t *m, uint64_t *out_base)
Locate the first mountable partition on a GPT disk (auto-select).
ra8_err_t priv_gpt_locate_partition(const ra8_fs_mount_t *m, uint8_t index, uint64_t *out_base)
Locate a GPT partition chosen by entry-array index.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
void priv_lock_release(void)
Drop the library lock taken by priv_lock_acquire.
void priv_lock_acquire(void)
Take the library lock, if the caller installed one.
static ra8_err_t internal_mount_locked(const ra8_fs_backend_t *backend, uint8_t index, ra8_fs_mount_t **out_handle)
Mount a volume – the guarded body of ra8_fs_mount() and ra8_fs_mount_partition().
static ra8_err_t internal_format_locked(const ra8_fs_backend_t *backend, const ra8_fs_format_opts_t *opts)
Lay down a fresh volume – the guarded body of ra8_fs_format().
static ra8_fs_mount_t * internal_alloc_mount_slot(void)
Allocate a free entry from the mount table; returns NULL if full.
static ra8_err_t internal_read_boot_sector(ra8_fs_mount_t *m, uint8_t index)
Read + parse the boot sector, transparently following MBR or GPT.
ra8_fs_file_t * priv_alloc_file_slot(void)
Allocate a free entry from the file table; returns NULL if full.
static ra8_err_t internal_mbr_select_entry(const uint8_t *buf, uint8_t index, uint64_t *out_base)
Return the first LBA of MBR primary entry index.
static ra8_err_t internal_unmount_locked(ra8_fs_mount_t *handle)
Release a mount slot – the guarded body of ra8_fs_unmount().
static ra8_err_t internal_compute_geometry(ra8_fs_mount_t *m)
Compute first_fat_lba, first_root_lba, first_data_lba, count_of_clusters.
static ra8_err_t internal_locate_indexed(const ra8_fs_mount_t *m, uint8_t index, uint64_t *out_base)
Resolve an explicit partition index to its first LBA.
static uint32_t internal_mbr_part0_lba(const uint8_t *buf)
Return partition 0's first LBA from an MBR in buf, or 0.
uint8_t g_fs_scratch[k_ra8_fs_sector_max]
Single max-sector scratch buffer reused across all I/O.
static uint8_t internal_bps_valid(uint32_t bs)
Test whether a backend block size is one this adapter supports.
static uint8_t s_sec_arena[k_fs_sec_roles][k_ra8_fs_sector_max]
The four fixed-role sector bounce buffers (#683).
uint8_t * priv_sec_fat2(void)
The FAT2-role sector buffer (the FAT12 straddle's second sector).
static ra8_fs_mount_t s_mounts[k_ra8_fs_max_mounts]
Mount table – max k_ra8_fs_max_mounts simultaneous volumes.
uint8_t * priv_sec_io(void)
The IO-role sector buffer (leaf data / bitmap sector transfers).
static ra8_err_t internal_probe_locked(const ra8_fs_backend_t *backend, ra8_fs_type_t *out_type)
Parse a backend into temporary state and return only its format type.
uint8_t * priv_sec_walk(void)
The WALK-role sector buffer (directory scans and entry RMW).
static ra8_err_t internal_mount_probe_bps(const ra8_fs_backend_t *backend, ra8_fs_mount_t *m)
Probe the backend's block size into a claimed mount slot.
uint8_t * priv_sec_fat(void)
The FAT-role sector buffer (priv_fat_get and the FAT setters).
static ra8_fs_file_t s_files[k_ra8_fs_max_files]
File handle table – max k_ra8_fs_max_files open at once.
ra8_err_t priv_parse_bpb_into_mount(ra8_fs_mount_t *m)
Parse the BPB layout fields out of g_fs_scratch into m.
@ k_mbr_part_entry_count
Primary partition entries in an MBR.
@ k_mbr_off_part0_lba
Partition 0 first-LBA (4 bytes, LE).
@ k_mbr_part_entry_stride
Bytes between primary partition entries.
@ k_mbr_off_part0_type
Partition 0 type byte (0 = unused).
@ k_bpb_sig_hi
Bpb sig hi.
@ k_bpb_sig_lo
Bpb sig lo.
@ k_gpt_part_type_protective
MBR type byte for a GPT disk.
@ k_fs_sec_role_io
Leaf data / bitmap sector transfers.
@ k_fs_sec_roles
Arena row count.
@ k_fs_sec_role_walk
Directory scans and entry read-modify-write.
@ k_fs_sec_role_fat
The sector holding a FAT entry.
@ k_fs_sec_role_fat2
FAT12 straddle: the following sector.
@ k_fmt_root_ents_f16
FAT12/16 root-directory entries.
@ k_cluster_count_fat12_max
MS FAT spec sec 3.5 boundary.
@ k_cluster_count_fat16_max
MS FAT spec sec 3.5 boundary.
@ k_bpb_off_tot_sec_32
MS FAT spec sec 3.1 "BPB_TotSec32".
@ k_bpb_off_root_ent_cnt
MS FAT spec sec 3.1 "BPB_RootEntCnt".
@ k_bpb_off_tot_sec_16
MS FAT spec sec 3.1 "BPB_TotSec16".
@ k_bpb_off_bytes_per_sec
MS FAT spec sec 3.1 "BPB_BytsPerSec".
@ k_bpb_off_signature_lo
Boot sig byte 1 (0x55).
@ k_bpb_off_num_fats
MS FAT spec sec 3.1 "BPB_NumFATs".
@ k_bpb_off_root_clus
MS FAT spec sec 3.5 "BPB_RootClus".
@ k_bpb_off_rsvd_sec_cnt
MS FAT spec sec 3.1 "BPB_RsvdSecCnt".
@ k_bpb_off_fat_sz_32
MS FAT spec sec 3.5 "BPB_FATSz32".
@ k_bpb_off_sec_per_clus
MS FAT spec sec 3.1 "BPB_SecPerClus".
@ k_bpb_off_fat_sz_16
MS FAT spec sec 3.1 "BPB_FATSz16".
@ k_bpb_off_signature_hi
Boot sig byte 2 (0xAA).
@ k_ra8_fs_partition_auto
Auto-select the first mountable partition.
ra8_fs_type_t
FAT variant detected from the BPB cluster-count rule.
@ k_ra8_fs_type_fat12
count_of_clusters < 4085.
@ k_ra8_fs_type_fat32
count_of_clusters >= 65525.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_type_fat16
4085 <= count_of_clusters < 65525.
@ k_ra8_fs_type_unknown
Not yet detected / mount failed.
@ k_ra8_fs_max_mounts
Max concurrent mount points.
@ k_ra8_fs_max_files
Max concurrent open file handles.
@ k_ra8_fs_dir_entry_bytes
MS FAT spec sec 6 "Directory Entry".
@ k_ra8_fs_sector_max
Largest supported sector size (4Kn).
@ k_ra8_fs_sector_min
Smallest supported sector size.
Block-device interface that ra8_fs runs on top of.
void * ctx
Caller-owned context passed back into the function pointers.
ra8_err_t(* get_capacity)(void *ctx, uint64_t *block_count, uint32_t *block_size)
Report the device size.
Computed on-disk geometry for one ra8_fs_format() run.
ra8_fs_type_t type
Resolved FAT variant.
Cached parse of one mounted FAT volume.
uint32_t reserved_sectors
BPB BPB_RsvdSecCnt.
uint32_t root_cluster
BPB BPB_RootClus (FAT32 only).
ra8_fs_type_t type
FAT12 / FAT16 / FAT32.
uint32_t bytes_per_sector
Sector size (BPB / VBR == backend).
uint32_t root_entries
BPB BPB_RootEntCnt (FAT12/16).
uint64_t total_sectors
BPB TotSec / exFAT VolumeLength.
uint32_t sectors_per_cluster
BPB BPB_SecPerClus.
uint32_t num_fats
BPB BPB_NumFATs.
ra8_fs_backend_t backend
Block-device backend.
uint32_t fat_size_sectors
BPB BPB_FATSz16 / BPB_FATSz32.
uint64_t first_root_lba
FAT12/16 fixed root-dir start.
uint64_t partition_base_lba
MBR/GPT partition start (0 = superfloppy).
uint32_t count_of_clusters
Per MS spec: data_sectors / SPC.
uint64_t first_data_lba
First sector of the data region.
uint64_t first_fat_lba
Computed: first FAT sector.