52 for (uint32_t i = 0U; i < len; i++) {
96 const uint64_t total_512 = total_sectors << scale;
107 if (clus_shift <= (uint32_t)bps_shift) {
110 return (uint8_t)(clus_shift - (uint32_t)bps_shift);
147 if (total_sectors <= g->fat_offset) {
150 uint32_t clusters = (uint32_t)((total_sectors - g->
fat_offset) / g->
spc);
154 const uint64_t fat_bytes = ((uint64_t)clusters + 2U) * 4U;
155 const uint32_t fat_len = (uint32_t)((fat_bytes + g->
bps - 1U) / g->
bps);
156 const uint32_t heap = g->
fat_offset + fat_len;
157 if (total_sectors <= heap) {
160 const uint32_t next = (uint32_t)((total_sectors - heap) / g->
spc);
163 if (next == clusters) {
169 const uint32_t cluster_bytes = g->
spc * g->
bps;
211 for (uint32_t i = 0U; i < g->
bps; i++) {
270 const ra8_err_t err = b->write_block(b->ctx, part_lba + lba, 1U, buf);
341 for (uint32_t i = 0U; i < g->
bps; i++) {
357 for (uint32_t i = 0U; i < g->
bps; i++) {
372 for (uint32_t i = 0U; i < (g->
bps / 4U); i++) {
462 for (uint32_t i = 0U; i < g->
bps; i++) {
515 for (uint32_t i = 0U; i < g->
bps; i++) {
519 for (uint32_t i = 0U; i < full; i++) {
559 if (label !=
nullptr) {
561 dst[(size_t)n * 2U] = (uint8_t)label[n];
562 dst[((size_t)n * 2U) + 1U] = 0U;
601 uint32_t upcase_csum,
616 for (uint32_t i = 0U; i < g->
bps; i++) {
673 const uint32_t cyl = lba / (hpc * spt);
674 const uint32_t head = (lba / spt) % hpc;
675 const uint32_t sec = (lba % spt) + 1U;
676 out3[0] = (uint8_t)head;
715 uint32_t part_sectors)
717 for (uint32_t i = 0U; i < bps; i++) {
769 uint8_t* out_bps_shift,
770 uint32_t* out_part_lba,
771 uint32_t* out_part_sectors)
773 uint32_t bps_shift = 0U;
774 for (uint32_t w = bps; w > 1U; w >>= 1U) {
778 const uint64_t min_total =
781 if (total_sectors < min_total) {
788 if ((total_sectors - part_lba) > (uint64_t)UINT32_MAX) {
791 *out_bps_shift = (uint8_t)bps_shift;
792 *out_part_lba = part_lba;
793 *out_part_sectors = (uint32_t)(total_sectors - part_lba);
799 uint64_t total_sectors,
803 uint8_t bps_shift = 0U;
804 uint32_t part_lba = 0U;
805 uint32_t part_sectors = 0U;
837 const uint64_t upcase_lba =
840 uint32_t upcase_csum = 0U;
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_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
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).
void priv_wr64(uint8_t *p, uint64_t v)
Encode a uint64_t into a byte buffer, little-endian.
void priv_wr32(uint8_t *p, uint32_t v)
Encode a little-endian uint32_t into a byte buffer.
void priv_wr16(uint8_t *p, uint16_t v)
Encode a little-endian uint16_t into a byte buffer.
static uint8_t internal_exfat_spc_shift(uint64_t total_sectors, uint8_t bps_shift)
Return the default SectorsPerClusterShift for an exFAT volume.
uint32_t priv_exfat_csum32(uint32_t cs, const uint8_t *buf, uint32_t len)
exFAT 32-bit rotate-right-add checksum (boot region + up-case table).
static ra8_err_t internal_exfat_fmt_place(uint64_t total_sectors, uint32_t bps, uint8_t *out_bps_shift, uint32_t *out_part_lba, uint32_t *out_part_sectors)
Size and place the exFAT partition on the device, or refuse.
static ra8_err_t internal_exfat_write_boot(const ra8_fs_backend_t *backend, const exfat_geom_t *g)
Write the complete exFAT main and backup boot regions (sectors 0-23).
static ra8_err_t internal_exfat_wr_dual(const ra8_fs_backend_t *b, uint64_t part_lba, uint32_t lba, const uint8_t *buf)
Write a sector to both its primary and backup locations in the exFAT boot region.
static void internal_exfat_build_vbr(uint8_t *sec, const exfat_geom_t *g)
Build the 512-byte exFAT Main Boot Sector (VBR) into sec.
static uint32_t internal_exfat_label_utf16(uint8_t *dst, const char *label)
Pack an ASCII volume label into a UTF-16LE buffer for the exFAT VolumeLabel entry.
static void internal_exfat_lba_to_chs(uint32_t lba, uint8_t *out3)
Encode an LBA as legacy CHS bytes using the 255-head / 63-sector geometry.
ra8_err_t priv_exfat_format(const ra8_fs_backend_t *backend, uint64_t total_sectors, uint32_t bps, const char *label)
Format the backend as a PC-standard partitioned exFAT volume (#102).
static void internal_exfat_put32(uint8_t *buf, uint32_t idx, uint32_t val)
Write a 32-bit little-endian word at slot idx in a sector buffer.
static ra8_err_t internal_exfat_write_bitmap(const ra8_fs_backend_t *backend, const exfat_geom_t *g)
Zero the allocation bitmap region, then mark the pre-allocated clusters.
static ra8_err_t internal_exfat_write_root(const ra8_fs_backend_t *backend, const exfat_geom_t *g, uint32_t upcase_csum, const char *label)
Write the exFAT root directory entry set (bitmap, up-case, label).
static ra8_err_t internal_exfat_write_boot_tail(const ra8_fs_backend_t *backend, const exfat_geom_t *g, uint32_t cs)
Write exFAT boot sectors 1-11 (ext-boot, OEM, reserved, checksum) to main and backup.
static ra8_err_t internal_exfat_write_fat(const ra8_fs_backend_t *backend, const exfat_geom_t *g)
Zero the exFAT FAT region, then seed the media, EOC, and chain entries.
static ra8_err_t internal_exfat_write_mbr(const ra8_fs_backend_t *backend, uint32_t bps, uint32_t part_lba, uint32_t part_sectors)
Write the MBR (LBA 0) with one type-0x07 exFAT partition at part_lba.
static ra8_err_t internal_exfat_geometry(uint64_t total_sectors, exfat_geom_t *g)
Resolve the exFAT region geometry for a device of total_sectors.
ra8_err_t priv_exfat_write_upcase(const ra8_fs_backend_t *backend, uint64_t abs_lba, uint32_t bps, uint32_t *out_csum)
Write the canonical exFAT up-case table and return its checksum.
ra8_err_t priv_fmt_clear_region(const ra8_fs_backend_t *backend, uint64_t lba, uint64_t count, uint32_t bps)
Clear count blocks at lba to zero – bulk-erase if the backend can.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
uint8_t g_fs_scratch[k_ra8_fs_sector_max]
Single max-sector scratch buffer reused across all I/O.
@ k_exfat_fmt_csum_hibit
Rotate-right wrap bit (32-bit).
@ k_exfat_fmt_fat_eoc
FatEntry end-of-chain.
@ k_exfat_fmt_clus_4k
log2 cluster BYTES for 4 KB clusters.
@ k_exfat_fmt_thr_256g
<= 256 GB -> 128 KB clusters.
@ k_exfat_fmt_first_clus
First cluster of the heap.
@ k_exfat_entry_label
Volume Label directory entry.
@ k_exfat_fmt_label_max
Volume-label cap (UTF-16 units).
@ k_exfat_fmt_fs_rev
FileSystemRevision = 1.00.
@ k_exfat_fmt_ext_sig
ExtendedBootSignature (sectors 1-8).
@ k_exfat_fmt_thr_32g
<= 32 GB -> 32 KB clusters.
@ k_exfat_fmt_csum_lba
Boot Checksum sector.
@ k_exfat_fmt_byte_full
A fully-allocated bitmap byte.
@ k_exfat_fmt_byte_bits
Bits per bitmap byte.
@ k_exfat_fmt_num_fats
exFAT uses a single FAT.
@ k_exfat_fmt_boot_sig
BootSignature (sector 0).
@ k_exfat_fmt_min_sectors
Smallest exFAT volume: 32 MiB.
@ k_exfat_fmt_thr_256m
<= 256 MB -> 4 KB clusters.
@ k_exfat_fmt_serial
Arbitrary volume-serial base.
@ k_exfat_fmt_upc_std_bytes
Canonical Microsoft up-case table len.
@ k_exfat_fmt_oem_lba
OEM Parameters sector.
@ k_exfat_fmt_backup_lba
Backup boot region start.
@ k_exfat_fmt_clus_256k
... 256 KB (> 256 GB cards).
@ k_exfat_fmt_clus_128k
... 128 KB.
@ k_exfat_fmt_csum_skip0
Checksum-excluded byte: VolumeFlags.
@ k_exfat_fmt_jump2
JumpBoot byte 2.
@ k_exfat_fmt_ext_count
Extended boot sector count.
@ k_exfat_fmt_boot_secs
12 main + 12 backup boot sectors.
@ k_exfat_fmt_geom_iters
Fixed-point geometry passes.
@ k_exfat_entry_upcase
Up-case Table directory entry.
@ k_exfat_fmt_percent
PercentInUse = 0% (fresh volume).
@ k_exfat_fmt_jump0
JumpBoot byte 0.
@ k_exfat_fmt_part_align
exFAT partition alignment: 1 MiB.
@ k_exfat_fmt_csum_skip2
Checksum-excluded byte: PercentInUse.
@ k_exfat_fmt_fat_media
FatEntry[0] media descriptor.
@ k_exfat_fmt_ext_first
First extended boot sector.
@ k_exfat_fmt_drive
DriveSelect (first fixed disk).
@ k_exfat_fmt_clus_32k
... 32 KB.
@ k_exfat_fmt_jump1
JumpBoot byte 1.
@ k_exfat_fmt_resv_lba
Reserved sector.
@ k_exfat_off_root_clus
FirstClusterOfRootDirectory.
@ k_exfat_off_fat_lba
FatOffset (sectors from VBR).
@ k_exfat_off_spc_shift
SectorsPerClusterShift (log2).
@ k_exfat_off_fat_len
FatLength (sectors).
@ k_exfat_off_bps_shift
BytesPerSectorShift (log2).
@ k_exfat_off_fsname
"EXFAT " filesystem-name field (8 chars).
@ k_exfat_off_num_fats
NumberOfFats.
@ k_exfat_off_clus_count
ClusterCount.
@ k_exfat_off_heap_lba
ClusterHeapOffset (sectors from VBR).
@ k_exfat_entry_bitmap
Allocation-bitmap directory entry.
@ k_exfat_bps_shift_min
log2(512): smallest BytesPerSectorShift.
@ k_exfat_fsname_len
"EXFAT " field length.
@ k_mbr_fmt_pe_lba
Entry: first LBA (4 bytes LE).
@ k_mbr_fmt_part0_off
First partition-table entry.
@ k_mbr_fmt_pe_boot
Entry: boot flag (relative).
@ k_mbr_fmt_chs_cyl_hi_mask
Cylinder bits [9:8] before packing.
@ k_mbr_fmt_pe_type
Entry: partition type byte.
@ k_mbr_fmt_chs_cyl_hi_shift
Shift packing cyl[9:8] into bits[7:6].
@ k_mbr_fmt_disk_sig_base
Arbitrary disk-signature base.
@ k_mbr_fmt_pe_nsect
Entry: sector count (4 bytes LE).
@ k_mbr_fmt_chs_spt
Conventional sectors-per-track.
@ k_mbr_fmt_chs_ovf_h
Overflow CHS head byte.
@ k_mbr_fmt_disk_sig_off
MBR disk signature (4 bytes LE).
@ k_mbr_fmt_pe_chs_start
Entry: start CHS (3 bytes).
@ k_mbr_fmt_chs_ovf_l
Overflow CHS cylinder-low byte.
@ k_mbr_fmt_chs_ovf_m
Overflow CHS sector/cyl-hi byte.
@ k_mbr_fmt_chs_heads
Conventional heads-per-cylinder.
@ k_mbr_fmt_chs_sec_mask
Low 6 bits of the CHS sector byte.
@ k_mbr_fmt_boot_none
Non-bootable partition.
@ k_mbr_fmt_pe_chs_end
Entry: end CHS (3 bytes).
@ k_mbr_fmt_type_exfat
Partition type: exFAT/NTFS/HPFS.
@ k_mbr_fmt_chs_max
1024*255*63: first LBA past CHS.
@ k_exfat_foff_drive
DriveSelect.
@ k_exfat_foff_part_off
PartitionOffset (64-bit).
@ k_exfat_de_upc_csum
Up-case entry: TableChecksum (32-bit).
@ k_exfat_foff_ext_sig
ExtendedBootSignature (extended sectors).
@ k_exfat_foff_jump
JumpBoot (3 bytes).
@ k_exfat_foff_boot_sig
BootSignature 0xAA55 (16-bit).
@ k_exfat_foff_vol_len
VolumeLength (64-bit).
@ k_exfat_foff_percent
PercentInUse.
@ k_exfat_de_lbl_name
Volume-label entry: UTF-16 label.
@ k_exfat_foff_fs_rev
FileSystemRevision (16-bit).
@ k_exfat_de_third
Offset of the 3rd dir entry in a set.
@ k_exfat_foff_serial
VolumeSerialNumber (32-bit).
@ k_exfat_de_lbl_cnt
Volume-label entry: CharacterCount.
@ k_exfat_de_data_len
Bitmap/Up-case entry: DataLength (64-bit).
@ k_exfat_de_second
Offset of the 2nd dir entry in a set.
@ k_exfat_de_first_clus
Bitmap/Up-case entry: FirstCluster.
@ k_ra8_fs_sector_min
Smallest supported sector size.
Resolved exFAT volume geometry produced by priv_exfat_geometry.
uint32_t upcase_clusters
Clusters the up-case table occupies.
uint32_t fat_offset
FatOffset (sectors from VBR).
uint32_t root_cluster
First cluster of the root directory.
uint32_t upcase_cluster
First cluster of the up-case table.
uint8_t bps_shift
BytesPerSectorShift (log2 of bps).
uint64_t total_sectors
Partition sector count (VolumeLength).
uint32_t used_clusters
bitmap + up-case + root (pre-allocated).
uint32_t spc
Sectors per cluster (1 << spc_shift).
uint32_t heap_offset
ClusterHeapOffset (sectors from VBR).
uint32_t bitmap_clusters
Clusters the bitmap occupies.
uint32_t fat_length
FatLength (sectors).
uint64_t part_lba
Partition start LBA (VBR sits here, not 0).
uint32_t bitmap_bytes
Allocation-bitmap logical size (DataLength).
uint32_t cluster_count
ClusterCount.
uint8_t spc_shift
SectorsPerClusterShift (log2).
uint32_t bps
Device sector size in bytes.
Block-device interface that ra8_fs runs on top of.
ra8_err_t(* write_block)(void *ctx, uint64_t lba, uint32_t count, const uint8_t *buf)
Write count consecutive blocks starting at lba.
void * ctx
Caller-owned context passed back into the function pointers.