|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
FAT/exFAT volume detection, geometry, and mount/unmount. More...
#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_fs.h"#include "ra8_fs_fat_internal.h"Go to the source code of this file.
Functions | |
| uint8_t * | priv_sec_walk (void) |
| The WALK-role sector buffer (directory scans and entry RMW). | |
| uint8_t * | priv_sec_fat (void) |
| The FAT-role sector buffer (priv_fat_get and the FAT setters). | |
| uint8_t * | priv_sec_fat2 (void) |
| The FAT2-role sector buffer (the FAT12 straddle's second sector). | |
| uint8_t * | priv_sec_io (void) |
| The IO-role sector buffer (leaf data / bitmap sector transfers). | |
| static ra8_fs_mount_t * | internal_alloc_mount_slot (void) |
| Allocate a free entry from the mount table; returns NULL if full. | |
| ra8_fs_file_t * | priv_alloc_file_slot (void) |
| Allocate a free entry from the file table; returns NULL if full. | |
| static uint8_t | internal_bps_valid (uint32_t bs) |
| Test whether a backend block size is one this adapter supports. | |
| 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. | |
| 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 uint32_t | internal_mbr_part0_lba (const uint8_t *buf) |
Return partition 0's first LBA from an MBR in buf, or 0. | |
| 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_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 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_err_t | internal_read_boot_sector (ra8_fs_mount_t *m, uint8_t index) |
| Read + parse the boot sector, transparently following MBR or GPT. | |
| 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. | |
| 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. | |
| 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_unmount_locked (ra8_fs_mount_t *handle) |
| Release a mount slot – the guarded body of ra8_fs_unmount(). | |
| 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_probe (const ra8_fs_backend_t *backend, ra8_fs_type_t *out_type) |
| Identify a FAT/exFAT volume without claiming a mount slot. | |
| 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. | |
Variables | |
| static ra8_fs_mount_t | s_mounts [k_ra8_fs_max_mounts] = {} |
| Mount table – max k_ra8_fs_max_mounts simultaneous volumes. | |
| static ra8_fs_file_t | s_files [k_ra8_fs_max_files] = {} |
| File handle table – max k_ra8_fs_max_files open at once. | |
| uint8_t | g_fs_scratch [k_ra8_fs_sector_max] = {} |
| Single max-sector scratch buffer reused across all I/O. | |
| static uint8_t | s_sec_arena [k_fs_sec_roles][k_ra8_fs_sector_max] = {} |
| The four fixed-role sector bounce buffers (#683). | |
| const uint8_t | k_zero_sector [k_ra8_fs_sector_max] = {} |
| Implementation of k_zero_sector – see the header contract. | |
FAT/exFAT volume detection, geometry, and mount/unmount.
Slot allocation, BPB parsing, MBR partition location, volume-type detection, and the public mount/unmount/format entry points. The GPT half of partition location lives in ra8_fs_fat_gpt.c (it outgrew this file when LBAs went 64-bit, #683); the two locators are called from here.
Definition in file ra8_fs_fat_mount.c.
|
static |
Allocate a free entry from the mount table; returns NULL if full.
Linear scan of s_mounts for an entry with in_use == 0.
| non-NULL | Pointer to a ra8_fs_mount_t with in_use == 0. |
| NULL | Mount table is full. |
Definition at line 107 of file ra8_fs_fat_mount.c.
References k_ra8_fs_max_mounts, and s_mounts.
Referenced by internal_mount_locked().
|
static |
Test whether a backend block size is one this adapter supports.
The supported sizes are the powers of two from k_ra8_fs_sector_min to k_ra8_fs_sector_max (512, 1024, 2048, 4096) – exactly the values the FAT specification allows for BPB_BytsPerSec and exFAT allows for BytesPerSectorShift.
| [in] | bs | Backend-reported block size in bytes. |
bs is supported, else 0. | 1 | bs is a power of two in 512..4096. |
| 0 | Anything else. |
bs came from a backend get_capacity callback. bs.Definition at line 161 of file ra8_fs_fat_mount.c.
References k_ra8_fs_sector_max, and k_ra8_fs_sector_min.
Referenced by internal_format_locked(), and internal_mount_probe_bps().
|
static |
Compute first_fat_lba, first_root_lba, first_data_lba, count_of_clusters.
Derives region LBAs from the BPB and chooses FAT type using the cluster-count thresholds in MS FAT spec sec 3.5.
| [in,out] | m | Mount with BPB fields already populated. |
| k_ra8_ok | Geometry computed. |
| k_ra8_err_validation_failed | Total sectors smaller than data start. |
Definition at line 229 of file ra8_fs_fat_mount.c.
References ra8_fs_mount_t::count_of_clusters, ra8_fs_mount_t::fat_size_sectors, ra8_fs_mount_t::first_data_lba, ra8_fs_mount_t::first_fat_lba, ra8_fs_mount_t::first_root_lba, k_cluster_count_fat12_max, k_cluster_count_fat16_max, k_ra8_err_validation_failed, k_ra8_fs_dir_entry_bytes, k_ra8_fs_type_fat12, k_ra8_fs_type_fat16, k_ra8_fs_type_fat32, k_ra8_ok, ra8_fs_mount_t::num_fats, priv_bps(), ra8_fs_mount_t::reserved_sectors, ra8_fs_mount_t::root_entries, ra8_fs_mount_t::sectors_per_cluster, ra8_fs_mount_t::total_sectors, and ra8_fs_mount_t::type.
Referenced by internal_mount_locked(), and internal_probe_locked().
|
static |
Lay down a fresh volume – the guarded body of ra8_fs_format().
Validates the backend and the requested geometry, then dispatches to the FAT or exFAT formatter. The public ra8_fs_format() is the wrapper that brackets this call with the library lock; the full contract is documented there.
| [in] | backend | Block-device backend to write. |
| [in] | opts | Format options (variant, label, cluster-size hint). |
| k_ra8_ok | Volume formatted. |
| k_ra8_err_null_ptr | backend or opts was NULL. |
| k_ra8_err_invalid_arg | Backend callbacks or geometry are unusable. |
| k_ra8_err_* | As documented for ra8_fs_format(). |
opts->type volume. Definition at line 401 of file ra8_fs_fat_mount.c.
References internal_bps_valid(), internal_format_locked(), k_fmt_root_ents_f16, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_fs_dir_entry_bytes, k_ra8_fs_type_exfat, k_ra8_fs_type_fat12, k_ra8_fs_type_fat16, k_ra8_fs_type_fat32, k_ra8_ok, priv_fmt_choose_geometry(), priv_fmt_emit_volume(), priv_fmt_reserved_for(), priv_fmt_spc_valid(), and ra8_fs_fmt_geom_t::type.
Referenced by internal_format_locked(), and ra8_fs_format().
|
static |
Resolve an explicit partition index to its first LBA.
Dispatches on the sector-0 partition-table type: a GPT disk (protective MBR type k_gpt_part_type_protective) selects GPT entry index, any other 0xAA55 MBR selects primary entry index. A sector 0 that carries no boot signature is not a partition table at all, so an explicit index has nothing to select and the caller's superfloppy request is refused. The signature bytes are tested separately (not as one compound decision) to mirror ::priv_mbr_part0_lba.
| [in] | m | Mount with sector 0 already in g_fs_scratch. |
| [in] | index | Zero-based partition index. |
| [out] | out_base | Receives the selected partition's first LBA. |
| k_ra8_ok | out_base holds the volume base. |
| k_ra8_err_not_found | No partition table, or an empty entry. |
| k_ra8_err_out_of_range | index is past the table. |
| k_ra8_err_not_supported | Unaddressable GPT geometry. |
| k_ra8_err_validation_failed | Malformed entry or GPT header. |
| k_ra8_err_* | Backend read failure. |
out_base is non-NULL. out_base holds a non-zero LBA. Definition at line 359 of file ra8_fs_fat_mount.c.
References g_fs_scratch, internal_mbr_select_entry(), k_bpb_off_signature_hi, k_bpb_off_signature_lo, k_bpb_sig_hi, k_bpb_sig_lo, k_gpt_part_type_protective, k_mbr_off_part0_type, k_ra8_err_not_found, and priv_gpt_locate_partition().
Referenced by internal_read_boot_sector().
|
static |
Return partition 0's first LBA from an MBR in buf, or 0.
Used only after the LBA-0 BPB parse fails: a standard SD card is MBR-partitioned, so the FAT boot sector lives at partition 0's start LBA, not at LBA 0. Returns 0 when buf is not a usable MBR (no 0x55AA, or an unused partition 0), which leaves the caller's original error in force.
| [in] | buf | Sector-0 contents (>= 512 bytes). |
| 0 | buf is not a usable MBR (no 0x55AA or an unused partition 0). |
| non-zero | Partition 0's first LBA. |
buf is non-NULL and holds at least one sector. buf is the contents of LBA 0. buf is unmodified. Definition at line 271 of file ra8_fs_fat_mount.c.
References k_bpb_off_signature_hi, k_bpb_off_signature_lo, k_bpb_sig_hi, k_bpb_sig_lo, k_mbr_off_part0_lba, k_mbr_off_part0_type, and priv_rd32().
Referenced by internal_read_boot_sector().
|
static |
Return the first LBA of MBR primary entry index.
Enumerates the four 16-byte primary entries. The type byte and first-LBA of entry index are read at k_mbr_off_part0_type and k_mbr_off_part0_lba plus index times k_mbr_part_entry_stride. Unlike the auto path (::priv_mbr_part0_lba), an out-of-range index, an empty slot, or a zero first-LBA are reported distinctly rather than folded to 0.
| [in] | buf | Sector-0 (MBR) contents (>= 512 bytes). |
| [in] | index | Zero-based primary-entry index. |
| [out] | out_base | Receives the entry's first LBA on success. |
| k_ra8_ok | out_base holds the entry's first LBA. |
| k_ra8_err_out_of_range | index is 4 or greater. |
| k_ra8_err_not_found | The selected entry is unused (type 0). |
| k_ra8_err_validation_failed | Allocated entry with a zero first LBA. |
buf is non-NULL and holds at least one sector. out_base is non-NULL. buf is unmodified. Definition at line 310 of file ra8_fs_fat_mount.c.
References k_mbr_off_part0_lba, k_mbr_off_part0_type, k_mbr_part_entry_count, k_mbr_part_entry_stride, k_ra8_err_not_found, k_ra8_err_out_of_range, k_ra8_err_validation_failed, k_ra8_ok, and priv_rd32().
Referenced by internal_locate_indexed().
|
static |
Mount a volume – the guarded body of ra8_fs_mount() and ra8_fs_mount_partition().
Allocates a mount slot, reads the boot sector for the requested index (k_ra8_fs_partition_auto for first-partition auto-select), parses the BPB, and computes the geometry.
| [in] | backend | Block-device backend to drive. |
| [in] | index | Partition selector, or k_ra8_fs_partition_auto. |
| [out] | out_handle | On success, opaque mount handle. |
| k_ra8_ok | Volume mounted. |
| k_ra8_err_null_ptr | NULL backend or out_handle. |
| k_ra8_err_invalid_arg | Backend missing required callbacks. |
| k_ra8_err_no_mem | Mount table is full. |
| k_ra8_err_out_of_range | index is past the partition table. |
| k_ra8_err_not_found | Selected entry empty, or no table. |
| k_ra8_err_validation_failed | Not a recognisable FAT volume. |
| k_ra8_err_* | Backend read failure. |
Definition at line 629 of file ra8_fs_fat_mount.c.
References internal_alloc_mount_slot(), internal_compute_geometry(), internal_mount_locked(), internal_mount_probe_bps(), internal_read_boot_sector(), k_ra8_err_no_mem, k_ra8_err_null_ptr, k_ra8_fs_type_exfat, k_ra8_ok, priv_alloc_state_bind(), priv_alloc_state_release(), and priv_fsinfo_seed().
Referenced by internal_mount_locked(), ra8_fs_mount(), and ra8_fs_mount_partition().
|
static |
Probe the backend's block size into a claimed mount slot.
The sector size is the DEVICE's block size, probed before the boot-sector parse so the parse can hold the volume to it (#683). A backend reporting a size outside 512..4096, or one that is not a power of two, is not mountable. Split out of ::priv_mount_locked so that function stays inside the function-size gate.
| [in] | backend | Block-device backend being mounted. |
| [in,out] | m | Claimed mount slot; bytes_per_sector is written. |
| k_ra8_ok | m->bytes_per_sector holds the device size. |
| k_ra8_err_invalid_arg | The reported block size is unsupported. |
| k_ra8_err_* | The get_capacity callback failed. |
backend and m are non-NULL; get_capacity is non-NULL. m was zeroed by the claim. m is left for the caller to abandon.Definition at line 533 of file ra8_fs_fat_mount.c.
References ra8_fs_mount_t::bytes_per_sector, ra8_fs_backend_t::ctx, ra8_fs_backend_t::get_capacity, internal_bps_valid(), k_ra8_err_invalid_arg, and k_ra8_ok.
Referenced by internal_mount_locked(), and internal_probe_locked().
|
static |
Parse a backend into temporary state and return only its format type.
| [in] | backend | Readable backend to probe. |
| [out] | out_type | Detected filesystem type. |
Definition at line 560 of file ra8_fs_fat_mount.c.
References ra8_fs_mount_t::backend, internal_compute_geometry(), internal_mount_probe_bps(), internal_probe_locked(), internal_read_boot_sector(), k_ra8_err_null_ptr, k_ra8_fs_partition_auto, k_ra8_fs_type_exfat, and k_ra8_ok.
Referenced by internal_probe_locked(), and ra8_fs_probe().
|
static |
Read + parse the boot sector, transparently following MBR or GPT.
When index is k_ra8_fs_partition_auto this tries the BPB/VBR at the current base (LBA 0 for a superfloppy); if that parse fails and sector 0 is an MBR it retargets to partition 0's start LBA, or – for a protective MBR (type 0xEE) – to the GPT partition the entry array selects (Basic Data preferred), then re-parses, leaving the original error in force when sector 0 is neither a volume, an MBR, nor a usable GPT. For any other index the superfloppy attempt is skipped and the chosen primary/GPT entry supplies the base directly (::priv_locate_indexed); an unaddressable or empty entry fails cleanly.
| [in,out] | m | Mount with backend bound and partition_base_lba == 0. |
| [in] | index | Partition selector, or k_ra8_fs_partition_auto. |
| k_ra8_ok | m holds the volume's BPB fields and base LBA. |
| k_ra8_err_* | The backend read failed or no volume was found. |
Definition at line 470 of file ra8_fs_fat_mount.c.
References g_fs_scratch, internal_locate_indexed(), internal_mbr_part0_lba(), k_gpt_part_type_protective, k_mbr_off_part0_type, k_ra8_fs_partition_auto, k_ra8_ok, ra8_fs_mount_t::partition_base_lba, priv_gpt_locate_volume(), priv_parse_volume(), and priv_read_sector().
Referenced by internal_mount_locked(), and internal_probe_locked().
|
static |
Release a mount slot – the guarded body of ra8_fs_unmount().
Writes the FAT32 FSInfo free count back if anything was allocated or freed, drops the allocator state, and marks the mount slot free. File data is not buffered, so there is nothing else to flush – callers must still close all files first.
| [in] | handle | Mount handle from ra8_fs_mount(). |
| k_ra8_ok | Volume unmounted. |
| k_ra8_err_null_ptr | handle was NULL. |
| k_ra8_err_invalid_state | handle is not currently mounted. |
| k_ra8_err_* | The FSInfo writeback failed; the volume is still unmounted. |
Definition at line 718 of file ra8_fs_fat_mount.c.
References internal_unmount_locked(), k_ra8_err_null_ptr, k_ra8_fs_type_unknown, priv_alloc_state_release(), and priv_fsinfo_flush().
Referenced by internal_unmount_locked(), and ra8_fs_unmount().
| ra8_fs_file_t * priv_alloc_file_slot | ( | void | ) |
Allocate a free entry from the file table; returns NULL if full.
Linear scan of s_files for an entry with in_use == 0.
| non-NULL | Pointer to a ra8_fs_file_t with in_use == 0. |
| NULL | File table is full. |
Definition at line 118 of file ra8_fs_fat_mount.c.
References k_ra8_fs_max_files, and s_files.
Referenced by internal_create_new(), internal_exfat_open_created(), internal_exfat_open_found(), internal_open_existing(), and priv_exfat_open().
| 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.
Validates the boot signature (0x55AA) and reads the BPB fields out of the boot sector scratch buffer.
| [in,out] | m | Mount to populate; backend already plugged in. |
| k_ra8_ok | Fields parsed successfully. |
| k_ra8_err_validation_failed | Bad signature or sanity-check fail. |
Definition at line 171 of file ra8_fs_fat_mount.c.
References ra8_fs_mount_t::bytes_per_sector, ra8_fs_mount_t::fat_size_sectors, g_fs_scratch, k_bpb_off_bytes_per_sec, k_bpb_off_fat_sz_16, k_bpb_off_fat_sz_32, k_bpb_off_num_fats, k_bpb_off_root_clus, k_bpb_off_root_ent_cnt, k_bpb_off_rsvd_sec_cnt, k_bpb_off_sec_per_clus, k_bpb_off_signature_hi, k_bpb_off_signature_lo, k_bpb_off_tot_sec_16, k_bpb_off_tot_sec_32, k_bpb_sig_hi, k_bpb_sig_lo, k_ra8_err_validation_failed, k_ra8_ok, ra8_fs_mount_t::num_fats, priv_rd16(), priv_rd32(), ra8_fs_mount_t::reserved_sectors, ra8_fs_mount_t::root_cluster, ra8_fs_mount_t::root_entries, ra8_fs_mount_t::sectors_per_cluster, and ra8_fs_mount_t::total_sectors.
Referenced by priv_parse_volume().
| uint8_t * priv_sec_fat | ( | void | ) |
The FAT-role sector buffer (priv_fat_get and the FAT setters).
See the arena discipline above.
| non-NULL | Always. |
Definition at line 66 of file ra8_fs_fat_mount.c.
References k_fs_sec_role_fat, and s_sec_arena.
Referenced by internal_exfat_fat_set_one(), internal_fat12_set_one(), internal_fat16_set_one(), internal_fat32_set_one(), and priv_fat_get().
| uint8_t * priv_sec_fat2 | ( | void | ) |
The FAT2-role sector buffer (the FAT12 straddle's second sector).
See the arena discipline above.
| non-NULL | Always. |
Definition at line 72 of file ra8_fs_fat_mount.c.
References k_fs_sec_role_fat2, and s_sec_arena.
Referenced by internal_fat12_set_one(), and priv_fat_get().
| uint8_t * priv_sec_io | ( | void | ) |
The IO-role sector buffer (leaf data / bitmap sector transfers).
See the arena discipline above.
| non-NULL | Always. |
Definition at line 78 of file ra8_fs_fat_mount.c.
References k_fs_sec_role_io, and s_sec_arena.
Referenced by internal_exchk_bitmap_pass(), internal_exfat_bitmap_window(), internal_exfat_read_entry(), internal_read_one_chunk(), internal_space_exfat_free(), internal_trunc_zero_span(), priv_exfat_bitmap_clear(), priv_exfat_bitmap_mark(), priv_exfat_bitmap_test(), priv_exfat_next_entry(), priv_exfat_seal_cluster(), priv_exfat_write_dir_set(), and priv_write_into_sector().
| uint8_t * priv_sec_walk | ( | void | ) |
The WALK-role sector buffer (directory scans and entry RMW).
See the arena discipline above. The pointer is to static storage of k_ra8_fs_sector_max bytes, valid for the whole program; only LIVENESS is scoped, by the role rules.
| non-NULL | Always. |
Definition at line 60 of file ra8_fs_fat_mount.c.
References k_fs_sec_role_walk, and s_sec_arena.
Referenced by internal_close_stamp(), internal_dir_cluster_init(), internal_dir_collect_chain(), internal_dir_erase_positions(), internal_dir_is_empty(), internal_fat_boot_set_label(), internal_fat_del_entry(), internal_fat_dir_next(), internal_fat_find_free_root(), internal_fat_find_vol_id(), internal_fat_fsinfo(), internal_fat_put_vol_id(), internal_fat_scan_cluster_dir(), internal_fat_scan_fixed_root(), internal_fat_trunc_commit(), internal_fsinfo_locate(), internal_get_label_fat(), internal_setattr_fat(), internal_truncate_existing(), internal_utime_fat(), priv_dir_commit(), priv_dir_find(), priv_dir_find_free_run(), priv_dir_find_long(), priv_fmt_emit_volume(), priv_fsinfo_flush(), and priv_fsinfo_seed().
|
nodiscard |
Format a block device as a fresh, empty FAT12/FAT16/FAT32/exFAT volume.
Lays down a complete volume so the very next ra8_fs_mount() on the same backend detects exactly opts->type. The FAT variants are written as a superfloppy (no MBR) at LBA 0; exFAT is written into an MBR partition (see below). For the FAT variants this is a classic BPB layout:
The cluster size is chosen (when opts->sectors_per_cluster == 0) so the resulting count_of_clusters lands in the band the requested type requires per Microsoft "FAT: General Overview of On-Disk Format" sec 3.5 (FAT12 < 4085, 4085 <= FAT16 < 65525, FAT32 >= 65525). If the backend's capacity cannot satisfy opts->type – too small for FAT16/FAT32, or too large for FAT12/FAT16 even at the maximum cluster size – the call fails without writing anything.
exFAT (k_ra8_fs_type_exfat) is written the way a PC writes it, so a card formatted here mounts on a desktop: a DOS/MBR partition table at LBA 0 with one type-0x07 partition aligned at 1 MiB, and the volume itself inside that partition rather than at LBA 0. ra8_fs_mount() follows the partition table back (ra8_fs_mount_t::partition_base_lba records where it landed), and also mounts a card partitioned by a desktop. Because the partition cannot start at sector 0, the device must be big enough for the 1 MiB alignment gap ON TOP OF the 32 MiB minimum volume – a 32 MiB card is no longer formattable.
Inside the partition exFAT lays down its own on-disk structures instead of a FAT BPB: the 12-sector boot region (Main + Backup) with the VBR checksum sector, the single FAT, the allocation-bitmap cluster(s), the canonical compressed up-case table (which may span several clusters), and a root-directory cluster carrying the volume-label, allocation-bitmap, and up-case-table system directory entries. The image is fsck.exfat-clean and round-trips through ra8_fs_mount() plus the whole exFAT file API: ra8_fs_open() in every mode, ra8_fs_read(), ra8_fs_write(), ra8_fs_write_file(), ra8_fs_rename(), and ra8_fs_unlink().
| [in] | backend | Block-device implementation (read/write/get_capacity all non-NULL). Its write_block is driven during the format. |
| [in] | opts | Format options. type selects the variant; label is an optional 0..11 char volume label; sectors_per_cluster pins the cluster size (0 = auto-select). |
| k_ra8_ok | Volume formatted; ready to mount. |
| k_ra8_err_null_ptr | backend or opts is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL callbacks, the reported block size is not a power of two in 512..4096, or sectors_per_cluster is non-zero and not a power of two in 1..128. |
| k_ra8_err_not_supported | opts->type is unknown / not a writable filesystem, or the device is too small to hold a partitioned exFAT volume (the 1 MiB alignment gap plus the 32 MiB minimum). |
| k_ra8_err_invalid_size | Capacity cannot satisfy opts->type. |
| k_ra8_err_* | Backend read/write failure (volume may be partially written on a mid-format I/O error). |
Definition at line 744 of file ra8_fs_fat_mount.c.
References internal_format_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_format().
Referenced by demo_fs_format_mount(), demo_fs_format_or_panic(), eoh_mount_or_halt(), etoc_mount_or_halt(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), internal_demo_mount(), internal_demo_mount(), internal_demo_probe_fat(), internal_format_mount(), internal_pc_mount_or_halt(), internal_ra8_io_roundtrip_format_mount(), internal_swap_run_one(), main(), ra8_fs_format(), ra8_io_roundtrip_mount(), and sdhi_demo_mount_via_io().
|
nodiscard |
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
Reads sector 0 and, if it is not itself a boot sector, follows the partition table to the first volume: MBR partition 0, or – on a GPT disk (protective MBR type 0xEE) – the first Microsoft Basic Data entry. It then validates the BPB signature and bytes-per-sector, computes the cluster count, dispatches to FAT12 / FAT16 / FAT32, and caches the layout in *out_handle. Exactly equivalent to ra8_fs_mount_partition() with k_ra8_fs_partition_auto; use that sibling to reach any other partition.
| [in] | backend | Block-device implementation. Must remain alive for the lifetime of the mount. |
| [out] | out_handle | Populated mount handle on success. |
| k_ra8_ok | Volume mounted successfully. |
| k_ra8_err_null_ptr | backend or out_handle is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL function pointers. |
| k_ra8_err_no_mem | No free mount slot. |
| k_ra8_err_validation_failed | BPB signature invalid / unsupported. |
Definition at line 762 of file ra8_fs_fat_mount.c.
References internal_mount_locked(), k_ra8_fs_partition_auto, priv_lock_acquire(), priv_lock_release(), and ra8_fs_mount().
Referenced by demo_fs_format_mount(), demo_fs_format_or_panic(), eoh_mount_or_halt(), etoc_mount_or_halt(), fileops_mount_volume(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), imp_mount_or_halt(), internal_demo_mount(), internal_demo_mount(), internal_format_mount(), internal_mount(), internal_mount_image(), internal_mount_sd(), internal_native_mount(), internal_pc_mount_or_halt(), internal_ra8_io_roundtrip_format_mount(), internal_swap_run_one(), main(), ra8_fs_mount(), ra8_io_roundtrip_mount(), sd_demo_mount_or_halt(), sdhi_demo_mount_via_io(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), and sh_sd_mount().
|
nodiscard |
Mount a FAT/exFAT volume from a specific partition of a block device.
Generalises ra8_fs_mount() with an explicit partition selector so a multi-partition card or disk exposes every volume, not just the first. Sector 0 decides the table type: a GPT disk (protective MBR type 0xEE) selects entry index of the GPT partition-entry array; any other 0xAA55 MBR selects primary entry index (0-3). The chosen partition's first LBA becomes out_handle->partition_base_lba and every subsequent access is partition-relative. Passing k_ra8_fs_partition_auto reproduces ra8_fs_mount() exactly, including transparent superfloppy (LBA 0) mounts; an explicit index requires a partition table, so a superfloppy with no table returns k_ra8_err_not_found.
| [in] | backend | Block-device implementation. Must remain alive for the lifetime of the mount. |
| [in] | index | Zero-based partition index, or k_ra8_fs_partition_auto. |
| [out] | out_handle | Populated mount handle on success. |
| k_ra8_ok | Volume mounted successfully. |
| k_ra8_err_null_ptr | backend or out_handle is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL function pointers. |
| k_ra8_err_no_mem | No free mount slot. |
| k_ra8_err_out_of_range | index is past the partition table. |
| k_ra8_err_not_found | The selected entry is empty, or there is no partition table to index. |
| k_ra8_err_not_supported | GPT entry-array geometry this backend cannot address (non-128-byte entries, or a first LBA above 32 bits). |
| k_ra8_err_validation_failed | BPB signature invalid / unsupported. |
Definition at line 773 of file ra8_fs_fat_mount.c.
References internal_mount_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_mount_partition().
Referenced by ra8_fs_mount_partition().
|
nodiscard |
Identify a FAT/exFAT volume without claiming a mount slot.
Runs the same superfloppy/MBR/GPT discovery and BPB/VBR validation as ra8_fs_mount(), but parses into temporary caller-invisible state and returns only the detected type. This is the authoritative probe used by the pluggable format registry: partitioned exFAT is not mistaken for an unknown format merely because LBA 0 is an MBR.
| [in] | backend | Readable block backend. |
| [out] | out_type | Detected FAT12/16/32 or exFAT type. |
| k_ra8_ok | A supported volume was validated. |
| k_ra8_err_null_ptr | Either argument was NULL. |
| k_ra8_err_invalid_arg | Required backend operations/capacity are invalid. |
| k_ra8_err_validation_failed | No supported volume is present. |
| k_ra8_err_* | Backend or partition-parse failure. |
out_type is untouched. Definition at line 753 of file ra8_fs_fat_mount.c.
References internal_probe_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_probe().
Referenced by internal_exfat_probe(), internal_fat_probe(), and ra8_fs_probe().
|
nodiscard |
Unmount a previously mounted volume and release its slot.
On a FAT32 volume carrying a valid FSInfo sector this is also where the free-cluster count and next-free hint are written back, so a card the firmware wrote reports the right free space on a desktop and fsck.fat stops calling the summary wrong. The slot is released even when that write fails – an unmount that could be refused would be worse than a stale free count.
| [in,out] | handle | Mount handle returned by ra8_fs_mount(). |
| k_ra8_ok | Slot released. |
| k_ra8_err_null_ptr | handle is NULL. |
| k_ra8_err_invalid_state | Slot was not in use. |
| k_ra8_err_* | FSInfo writeback failed; the slot is still released. |
Definition at line 782 of file ra8_fs_fat_mount.c.
References internal_unmount_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_unmount().
Referenced by demo_thread_entry(), fileops_run_ladder(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), internal_finish_image(), internal_native_unmount(), internal_run_font(), internal_swap_run_one(), main(), priv_mkbookimg_build_image(), ra8_fs_unmount(), ra8_sdfont_load(), selftest_host_pass(), and selftest_host_pass().
| uint8_t g_fs_scratch[k_ra8_fs_sector_max] = {} |
Single max-sector scratch buffer reused across all I/O.
Shared by every FAT/exFAT translation unit; declared extern in ra8_fs_fat_internal.h and defined here exactly once. Sized to k_ra8_fs_sector_max so a 4Kn medium fits without allocation.
One module-wide bounce buffer for every BPB, FAT, directory, and data-sector access. Sized to k_ra8_fs_sector_max so a 4Kn medium fits; a 512-byte mount simply uses the first quarter. Defined once in ra8_fs_fat_mount.c.
Definition at line 40 of file ra8_fs_fat_mount.c.
Referenced by internal_exfat_write_bitmap(), internal_exfat_write_boot(), internal_exfat_write_boot_tail(), internal_exfat_write_fat(), internal_exfat_write_mbr(), internal_exfat_write_root(), internal_fmt_seed_fats(), internal_fmt_write_fsinfo(), internal_gpt_read_geom(), internal_gpt_scan_entries(), internal_locate_indexed(), internal_read_boot_sector(), priv_exfat_write_upcase(), priv_gpt_locate_partition(), priv_parse_bpb_into_mount(), and priv_parse_volume().
| const uint8_t k_zero_sector[k_ra8_fs_sector_max] = {} |
Implementation of k_zero_sector – see the header contract.
One whole sector of zero bytes, in read-only storage.
Definition at line 57 of file ra8_fs_fat_mount.c.
Referenced by internal_dir_cluster_init(), internal_dir_grow(), internal_exfat_close_gap(), and priv_exfat_zero_cluster().
|
static |
File handle table – max k_ra8_fs_max_files open at once.
Definition at line 32 of file ra8_fs_fat_mount.c.
Referenced by internal_file_valid(), internal_free_file(), priv_alloc_file_slot(), ra8_io_vfs_init(), and ra8_io_vfs_unmount().
|
static |
Mount table – max k_ra8_fs_max_mounts simultaneous volumes.
Definition at line 29 of file ra8_fs_fat_mount.c.
Referenced by internal_alloc_mount_slot().
|
static |
The four fixed-role sector bounce buffers (#683).
Backing storage for priv_sec_walk / priv_sec_fat / priv_sec_fat2 / priv_sec_io – see the arena discipline in ra8_fs_fat_bytes_internal.h. Static because 4 KiB frames do not belong on firmware stacks; four buffers because that is the whole simultaneous-liveness depth of the call graph.
Definition at line 54 of file ra8_fs_fat_mount.c.
Referenced by priv_sec_fat(), priv_sec_fat2(), priv_sec_io(), and priv_sec_walk().