147 for (uint32_t i = 0U; (i + 1U) < alloc; i++) {
148 const uint32_t here = first + i;
190 if (file->alloc_clusters == 0U) {
193 if ((file->no_fat_chain != 0U) && (next == (file->tail_cluster + 1U))) {
196 if (file->no_fat_chain != 0U) {
199 file->alloc_clusters,
205 file->no_fat_chain = 0U;
245 uint64_t bmp_lba = 0U;
250 const uint32_t prefer = (file->alloc_clusters > 0U) ? (file->tail_cluster + 1U) : 0U;
265 if (file->alloc_clusters == 0U) {
266 file->first_cluster = next;
267 file->cur_cluster = next;
268 file->walk_cache_idx = 0U;
269 file->walk_cache_cluster = next;
271 file->tail_cluster = next;
272 file->alloc_clusters++;
279 while (file->alloc_clusters < need) {
413 if ((*nofat != 0U) && (next == (tail + 1U))) {
480 for (uint32_t k = 1U; k < count; k++) {
539 uint64_t bmp_lba = 0U;
579 const uint32_t new_alloc = alloc + 1U;
627 if (file->no_fat_chain != 0U) {
628 *out = file->first_cluster + idx;
636 uint32_t from = file->first_cluster;
639 if (idx >= file->walk_cache_idx) {
640 from = file->walk_cache_cluster;
641 hops = idx - file->walk_cache_idx;
645 for (uint32_t i = 0U; i < hops; i++) {
656 file->walk_cache_idx = idx;
657 file->walk_cache_cluster = cur;
699 const uint32_t idx = (uint32_t)(pos / cbytes);
709 file->cur_cluster = cur;
710 const uint32_t in_cluster = (uint32_t)(pos % cbytes);
712 *out_off = in_cluster %
priv_bps(m);
747 while (file->valid_bytes < file->offset) {
755 const uint64_t gap = file->offset - file->valid_bytes;
757 if (gap < (uint64_t)room) {
764 file->valid_bytes += n;
776 uint32_t consumed = 0U;
777 while (consumed < len) {
785 uint32_t put = len - consumed;
795 if (file->offset > file->valid_bytes) {
796 file->valid_bytes = file->offset;
798 if (file->offset > file->size_bytes) {
799 file->size_bytes = file->offset;
844 if (file->alloc_clusters > 0U) {
845 first = file->first_cluster;
846 if (file->no_fat_chain != 0U) {
889 .entry_in_cluster = file->entry_set_index,
891 for (uint32_t k = 0U; k < file->entry_set_count; k++) {
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
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 priv_fat_get(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t *out_value)
Fetch the FAT entry for cluster, returning the next-cluster value.
void priv_wr64(uint8_t *p, uint64_t v)
Encode a uint64_t into a byte buffer, little-endian.
ra8_err_t priv_fat_set(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t value)
Write value into the FAT entry for cluster across every FAT copy.
uint64_t priv_cluster_to_lba(const ra8_fs_mount_t *m, uint32_t cluster)
Convert a cluster number into its first data-region LBA.
uint8_t priv_is_eoc(const ra8_fs_mount_t *m, uint32_t value)
Test whether value is an end-of-chain marker for this FAT type.
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
uint32_t priv_eoc_write(const ra8_fs_mount_t *m)
End-of-chain value to write for this FAT type.
void priv_wr32(uint8_t *p, uint32_t v)
Encode a little-endian uint32_t into a byte buffer.
uint32_t priv_cluster_bytes(const ra8_fs_mount_t *m)
One mounted volume's cluster size in bytes.
void priv_wr16(uint8_t *p, uint16_t v)
Encode a little-endian uint16_t into a byte buffer.
void priv_alloc_hint_set(const ra8_fs_mount_t *m, uint32_t cluster)
Move the next-free hint forward to cluster.
ra8_err_t priv_exfat_bitmap_lba(const ra8_fs_mount_t *m, uint64_t *out_lba)
Resolve the exFAT allocation bitmap's first LBA, once per mount.
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_exfat_seal_cluster(const ra8_fs_mount_t *m, uint32_t clus)
Replace every end-of-directory marker in a cluster with an unused one.
ra8_err_t priv_exfat_zero_cluster(const ra8_fs_mount_t *m, uint32_t clus)
Zero every sector of one cluster.
ra8_err_t priv_exfat_next_entry(const ra8_fs_mount_t *m, exfat_cursor_t *cur, uint8_t *out)
Fetch the next 32-byte directory entry, following the cluster chain.
static ra8_err_t internal_exfat_slice_at(ra8_fs_file_t *file, uint64_t pos, uint64_t *out_lba, uint32_t *out_off, uint32_t *out_room)
Locate byte position pos on the volume, allocating to reach it.
static ra8_err_t internal_exfat_close_gap(ra8_fs_file_t *file)
Fill [valid_bytes, offset) with real zeros.
static ra8_err_t internal_exfat_cluster_at(ra8_fs_file_t *file, uint32_t idx, uint32_t *out)
Resolve the cluster at chain index idx of an already-grown file.
static void internal_exfat_patch_stream(const ra8_fs_file_t *file, uint8_t *strm)
Patch a Stream-extension entry to describe the handle's current state.
static ra8_err_t internal_exfat_link_cluster(ra8_fs_file_t *file, uint32_t next)
Attach a freshly allocated cluster to the file's allocation.
static ra8_err_t internal_exfat_dir_relen(const ra8_fs_mount_t *m, const exfat_dir_t *dir, uint64_t new_bytes, uint8_t nofat)
Rewrite a grown directory's own Stream entry to describe its new run.
ra8_err_t priv_exfat_grow_dir(const ra8_fs_mount_t *m, exfat_dir_t *dir)
Append one zeroed cluster to a directory, keeping its entry set true.
static ra8_err_t internal_exfat_dir_link(const ra8_fs_mount_t *m, uint32_t first, uint32_t alloc, uint32_t tail, uint8_t *nofat, uint32_t next)
Attach next to a directory's run, converting to a chain if needed.
static ra8_err_t internal_exfat_dir_survey(const ra8_fs_mount_t *m, const exfat_dir_t *dir, uint32_t *out_alloc, uint32_t *out_tail, uint8_t *out_nofat)
Survey a directory's current allocation into run coordinates.
static ra8_err_t internal_exfat_gather_set(const ra8_fs_file_t *file, uint8_t *set, exfat_setpos_t *at_file, exfat_setpos_t *at_stream)
Read a file's entry set back into set, recording where it lives.
ra8_err_t priv_exfat_write_stream(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Stream bytes into an exFAT file, growing its allocation as needed.
ra8_err_t priv_exfat_ensure_clusters(ra8_fs_file_t *file, uint32_t need)
Grow a file's allocation until it owns at least need clusters.
static ra8_err_t internal_exfat_materialize_run(const ra8_fs_mount_t *m, uint32_t first, uint32_t alloc, uint32_t tail, uint32_t next)
Write a real FAT chain over a contiguous run, ending at next.
static ra8_err_t internal_exfat_dir_append(const ra8_fs_mount_t *m, const exfat_dir_t *dir, uint32_t alloc, uint32_t tail, uint8_t *nofat)
Allocate one cluster, zero it, link it to the run, seal the old tail.
static ra8_err_t internal_exfat_grow_one(ra8_fs_file_t *file)
Add one cluster to a file's allocation.
static ra8_err_t internal_exfat_pick_cluster(const ra8_fs_mount_t *m, uint64_t bmp_lba, uint32_t prefer, uint32_t *out)
Choose the next cluster to allocate, preferring the tail's successor.
ra8_err_t priv_exfat_flush_set(ra8_fs_file_t *file)
Rewrite a file's entry set from the handle, checksum last.
ra8_err_t priv_exfat_bitmap_mark(const ra8_fs_mount_t *m, uint64_t bmp_lba, uint32_t clus, uint32_t count)
Mark a contiguous cluster run as allocated in the bitmap.
ra8_err_t priv_exfat_bitmap_test(const ra8_fs_mount_t *m, uint64_t bmp_lba, uint32_t clus, uint8_t *out_free)
Read one allocation-bitmap bit: is this cluster free?
ra8_err_t priv_exfat_bitmap_scan(const ra8_fs_mount_t *m, uint64_t bmp_lba, uint32_t need, uint32_t *out_clus)
Find a contiguous free run, starting from the mount's next-free hint.
uint16_t priv_exfat_set_checksum(const uint8_t *set, uint32_t bytes)
Compute the SetChecksum over a built directory entry set.
ra8_err_t priv_exfat_write_dir_set(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t idx, const uint8_t *set, uint32_t bytes)
Write a pre-built entry set into consecutive directory entries.
ra8_err_t priv_write_into_sector(const ra8_fs_mount_t *m, uint64_t lba, uint32_t off_in_sector, const uint8_t *src, uint32_t put)
Implementation of priv_write_into_sector() – one read-modify-write.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
void priv_exfat_file_stamp_write(uint8_t *file_entry)
Advance an exFAT File entry's modification (and access) stamps.
@ k_exfat_strm_off_dlen
Stream-ext DataLength (low 32 used).
@ k_exfat_strm_off_clus
Stream-ext FirstCluster.
@ k_exfat_strm_off_flags
Stream-ext GeneralSecondaryFlags.
@ k_exfat_off_file_csum
File entry: SetChecksum (2 bytes).
@ k_exfat_entry_bytes
Directory entry size.
@ k_exfat_off_strm_valid
Stream entry: ValidDataLength (8 B).
@ k_exfat_secflag_poss
GeneralSecondaryFlags: AllocationPossible.
@ k_exfat_secflag_alloc
AllocationPossible | NoFatChain.
@ k_exfat_off_file_attr
File entry: FileAttributes (2 bytes).
@ k_exfat_off_file_secnt
File entry: SecondaryCount.
@ k_exfat_max_set_bytes
(2 + ceil(64/15)) * 32 = 7 entries.
@ k_exfat_attr_archive
FileAttributes: archive.
@ k_exfat_set_writable
1 File + 1 Stream + 5 Name (64 chars).
@ k_cluster_first_data
Cluster numbers start at 2.
Linear cursor over a directory's 32-byte entries.
uint32_t cluster
Current directory cluster.
uint32_t entry_in_cluster
Next entry index within the cluster.
Identifies the exFAT directory a lookup, scan or link operates in.
uint32_t self_cluster
Parent cluster holding this dir's File entry; 0 => root.
uint32_t cluster
First cluster of the directory.
uint32_t self_index
File-entry index within self_cluster.
uint32_t contig_end
One past the run's last cluster; 0 => FAT-chained.
Directory position (cluster + entry index) of one 32-byte entry.
uint32_t index
Entry index within that cluster (0-based).
uint32_t cluster
Directory cluster holding the entry.
Cached parse of one mounted FAT volume.
uint32_t count_of_clusters
Per MS spec: data_sectors / SPC.