ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fs_fat_fmt.c File Reference

FAT12/16/32 formatter (mkfs) for the ra8_fs adapter. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_fs.h"
#include "ra8_fs_fat_internal.h"
Include dependency graph for ra8_fs_fat_fmt.c:

Go to the source code of this file.

Functions

uint32_t priv_fmt_reserved_for (ra8_fs_type_t type)
 Map a requested FAT type to its reserved-sector count.
static uint64_t internal_fmt_clusters_for (const ra8_fs_fmt_geom_t *g, uint32_t spc, uint32_t *out_fatsz)
 Compute the cluster count for a trial cluster size.
static bool internal_fmt_count_in_band (ra8_fs_type_t type, uint64_t count)
 Test whether a cluster count is valid for a given FAT type.
static uint32_t internal_fmt_log2 (uint32_t v)
 log2 of a power-of-two value.
static uint32_t internal_fmt_fat32_default_spc (uint64_t total_sectors, uint32_t bps)
 Default FAT32 cluster size for a device, per the Microsoft table.
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.
static void internal_fmt_boot_prologue (uint8_t *sec)
 Write the shared boot prologue (jump + OEM) into the scratch sector.
void priv_fmt_label_field (uint8_t *dst, const char *label)
 Pad an ASCII volume label into an 11-byte BS_VolLab / label field.
static void internal_fmt_write_totals (uint8_t *sec, const ra8_fs_fmt_geom_t *g)
 Write a totals/FAT-size pair into the BPB, choosing 16- vs 32-bit.
static void internal_fmt_build_bpb_f16 (uint8_t *sec, const ra8_fs_fmt_geom_t *g, const char *label)
 Build the FAT12/FAT16 boot sector into the scratch buffer.
static void internal_fmt_build_bpb_f32 (uint8_t *sec, const ra8_fs_fmt_geom_t *g, const char *label)
 Build the FAT32 boot sector into the scratch buffer.
static ra8_err_t internal_fmt_zero_run (const ra8_fs_backend_t *backend, uint64_t lba, uint64_t count, uint32_t bps)
 Zero a run of sectors on the backend in multi-sector chunks.
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.
static ra8_err_t internal_fmt_seed_fats (const ra8_fs_backend_t *backend, const ra8_fs_fmt_geom_t *g)
 Seed the reserved FAT entries (and FAT32 root-cluster EOC) per copy.
static ra8_err_t internal_fmt_write_fsinfo (const ra8_fs_backend_t *backend, const ra8_fs_fmt_geom_t *g, const uint8_t *boot_sec)
 Write the FAT32 FSInfo sector (and the backup boot sector copy).
bool priv_fmt_spc_valid (uint8_t spc)
 Validate a caller-pinned sectors-per-cluster value.
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.

Variables

static const uint8_t s_fmt_zero_chunk [k_fmt_zero_chunk_bytes] = {}
 All-zero source for the chunked FAT/root wipe (read-only, in flash).

Detailed Description

FAT12/16/32 formatter (mkfs) for the ra8_fs adapter.

Geometry selection, BPB/FSInfo construction, FAT seeding, and the region-clear helpers shared with the exFAT formatter.

Since
0.1.0

Definition in file ra8_fs_fat_fmt.c.

Function Documentation

◆ internal_fmt_boot_prologue()

void internal_fmt_boot_prologue ( uint8_t * sec)
static

Write the shared boot prologue (jump + OEM) into the scratch sector.

Lays the 3-byte short-jump opcode and the 8-byte OEM name at the head of the boot sector. The scratch buffer must be zeroed first.

Parameters
[out]secZeroed 512-byte boot sector under construction.
Precondition
sec is non-NULL and at least 512 bytes, pre-zeroed.
The caller owns sec for the duration.
Postcondition
Bytes 0..2 and 3..10 hold the jump + OEM fields.
No bytes past offset 10 are touched.
Note
Not reentrant against the same buffer.
Since
0.1.0

Definition at line 262 of file ra8_fs_fat_fmt.c.

References k_filename_base_len, k_fmt_jmp_byte0, k_fmt_jmp_byte1, k_fmt_jmp_byte2, k_fmt_off_jmp0, k_fmt_off_jmp1, k_fmt_off_jmp2, k_fmt_off_oem, and priv_byte_copy().

Referenced by internal_fmt_build_bpb_f16(), and internal_fmt_build_bpb_f32().

◆ internal_fmt_build_bpb_f16()

void internal_fmt_build_bpb_f16 ( uint8_t * sec,
const ra8_fs_fmt_geom_t * g,
const char * label )
static

Build the FAT12/FAT16 boot sector into the scratch buffer.

Writes the full BPB: bytes-per-sector, the chosen cluster size, one reserved sector, two FATs, the 512-entry root directory, media descriptor, geometry, an extended boot signature with volume serial

  • label, the "FAT12 "/"FAT16 " type string, and the 0x55AA boot signature.
Parameters
[out]secZeroed boot sector under construction.
[in]gResolved geometry.
[in]labelOptional volume label.
Precondition
sec, g are non-NULL; sec pre-zeroed.
g->type is FAT12 or FAT16.
Postcondition
sec holds a complete FAT12/16 boot sector.
Byte 510/511 hold the 0x55/0xAA signature.
Note
Not reentrant against the same buffer.
Since
0.1.0

Definition at line 349 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, internal_fmt_boot_prologue(), internal_fmt_write_totals(), k_bpb_off_bytes_per_sec, k_bpb_off_num_fats, 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_sig_hi, k_bpb_sig_lo, k_filename_base_len, k_fmt_drvnum_hd, k_fmt_ext_bootsig, k_fmt_media_fixed, k_fmt_num_fats, k_fmt_num_heads, k_fmt_off_f16_bootsig, k_fmt_off_f16_drvnum, k_fmt_off_f16_fstype, k_fmt_off_f16_label, k_fmt_off_f16_volid, k_fmt_off_media, k_fmt_off_num_heads, k_fmt_off_sec_per_trk, k_fmt_sec_per_trk, k_fmt_volid_base, k_ra8_fs_type_fat12, priv_byte_copy(), priv_fmt_label_field(), priv_wr16(), priv_wr32(), ra8_fs_fmt_geom_t::reserved_sectors, ra8_fs_fmt_geom_t::root_entries, ra8_fs_fmt_geom_t::sectors_per_cluster, ra8_fs_fmt_geom_t::total_sectors, and ra8_fs_fmt_geom_t::type.

Referenced by priv_fmt_emit_volume().

◆ internal_fmt_build_bpb_f32()

void internal_fmt_build_bpb_f32 ( uint8_t * sec,
const ra8_fs_fmt_geom_t * g,
const char * label )
static

Build the FAT32 boot sector into the scratch buffer.

Writes the FAT32 BPB: zero root entries, 32-bit totals + FAT size, root cluster 2, the FSInfo sector number, the backup-boot location, an extended boot signature with serial + label, the "FAT32 " type string, and the 0x55AA signature.

Parameters
[out]secZeroed boot sector under construction.
[in]gResolved geometry (FAT32).
[in]labelOptional volume label.
Precondition
sec, g are non-NULL; sec pre-zeroed.
g->type is FAT32.
Postcondition
sec holds a complete FAT32 boot sector.
Byte 510/511 hold the 0x55/0xAA signature.
Note
Not reentrant against the same buffer.
Since
0.1.0

Definition at line 396 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, internal_fmt_boot_prologue(), internal_fmt_write_totals(), k_bpb_off_bytes_per_sec, k_bpb_off_num_fats, k_bpb_off_root_clus, k_bpb_off_rsvd_sec_cnt, k_bpb_off_sec_per_clus, k_bpb_off_signature_hi, k_bpb_off_signature_lo, k_bpb_sig_hi, k_bpb_sig_lo, k_filename_base_len, k_fmt_bkboot_sector, k_fmt_drvnum_hd, k_fmt_ext_bootsig, k_fmt_fsinfo_sector, k_fmt_media_fixed, k_fmt_num_fats, k_fmt_num_heads, k_fmt_off_f32_bkboot, k_fmt_off_f32_bootsig, k_fmt_off_f32_drvnum, k_fmt_off_f32_fsinfo, k_fmt_off_f32_fstype, k_fmt_off_f32_label, k_fmt_off_f32_volid, k_fmt_off_media, k_fmt_off_num_heads, k_fmt_off_sec_per_trk, k_fmt_root_clus_f32, k_fmt_sec_per_trk, k_fmt_volid_base, priv_byte_copy(), priv_fmt_label_field(), priv_wr16(), priv_wr32(), ra8_fs_fmt_geom_t::reserved_sectors, ra8_fs_fmt_geom_t::sectors_per_cluster, and ra8_fs_fmt_geom_t::total_sectors.

Referenced by priv_fmt_emit_volume().

◆ internal_fmt_clusters_for()

uint64_t internal_fmt_clusters_for ( const ra8_fs_fmt_geom_t * g,
uint32_t spc,
uint32_t * out_fatsz )
static

Compute the cluster count for a trial cluster size.

Mirrors the mount-side geometry: subtracts the reserved, FAT, and fixed-root regions from the device, then divides the remaining data sectors by spc. The FAT size is sized to index every data cluster (entries_per_sector * spc + 2 accounts for the two reserved entries) and is reported back so the caller can store it.

Parameters
[in]gGeometry holding total/reserved/root spans and the type.
[in]spcTrial sectors-per-cluster (power of two).
[out]out_fatszSectors per FAT copy for this spc.
Returns
Resulting data-cluster count, or 0 if the device is too small.
Return values
0Reserved + FAT + root already exceed the device.
1..UINT64_MAXCluster count for spc (band checks reject any value FAT itself cannot express).
Precondition
g and out_fatsz are non-NULL.
spc is non-zero.
Postcondition
*out_fatsz holds the FAT size for spc.
No other state modified.
Note
Pure aside from *out_fatsz; thread-safe vs other readers.
Since
0.1.0

Definition at line 61 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, k_fmt_fat16_entry_bytes, k_fmt_fat32_entry_bytes, k_fmt_num_fats, k_ra8_fs_type_fat32, ra8_fs_fmt_geom_t::reserved_sectors, ra8_fs_fmt_geom_t::root_sectors, ra8_fs_fmt_geom_t::total_sectors, and ra8_fs_fmt_geom_t::type.

Referenced by priv_fmt_choose_geometry().

◆ internal_fmt_count_in_band()

bool internal_fmt_count_in_band ( ra8_fs_type_t type,
uint64_t count )
static

Test whether a cluster count is valid for a given FAT type.

Applies the MS FAT spec sec 3.5 thresholds: FAT12 needs count < 4085, FAT16 needs 4085 <= count < 65525, FAT32 needs 65525 <= count <= k_fmt_fat32_clus_cap.

Parameters
[in]typeRequested FAT variant.
[in]countTrial cluster count.
Returns
Whether count lands in type's valid band.
Return values
truecount is valid for type.
falsecount is outside type's band.
Precondition
type is FAT12/FAT16/FAT32.
count was produced by priv_fmt_clusters_for().
Postcondition
No state modified.
Result is purely a function of inputs.
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 108 of file ra8_fs_fat_fmt.c.

References k_cluster_count_fat12_max, k_cluster_count_fat16_max, k_fmt_fat32_clus_cap, k_ra8_fs_type_fat12, and k_ra8_fs_type_fat16.

Referenced by priv_fmt_choose_geometry().

◆ internal_fmt_fat32_default_spc()

uint32_t internal_fmt_fat32_default_spc ( uint64_t total_sectors,
uint32_t bps )
static

Default FAT32 cluster size for a device, per the Microsoft table.

Implements the DskSzToSecPerClus tiers from the MS FAT spec (fatgen103 sec 3.3). Used as the starting cluster size for the FAT32 auto-sweep so a large card does not land on the minimum cluster (which the cluster cap technically allows but which produces a multi-hundred-MB FAT that takes minutes to zero over SPI). The sweep can still grow spc further for cards above the table's range. The table's thresholds are counts of 512-byte sectors and its picks are cluster BYTES, so both are converted through the device's real sector size – a 4Kn card lands on the same cluster byte size a 512-byte card of equal capacity does.

Parameters
[in]total_sectorsWhole-device sector count (device sectors).
[in]bpsDevice sector size in bytes (power of two, 512..4096).
Returns
Sectors-per-cluster (power of two >= 1).
Return values
1Device is <= 260 MB (or the cluster equals one sector).
64512-byte device above 32 GB.
Precondition
total_sectors is the card capacity in device sectors.
bps is a power of two in 512..4096.
Postcondition
Return value is a power of two >= 1.
No state is modified (pure function, no side effects).
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 185 of file ra8_fs_fat_fmt.c.

References internal_fmt_log2(), k_fmt_f32_clus_16k, k_fmt_f32_clus_32k, k_fmt_f32_clus_4k, k_fmt_f32_clus_512b, k_fmt_f32_clus_8k, k_fmt_f32_thr_16g, k_fmt_f32_thr_260m, k_fmt_f32_thr_32g, k_fmt_f32_thr_8g, and k_ra8_fs_sector_min.

Referenced by priv_fmt_choose_geometry().

◆ internal_fmt_log2()

uint32_t internal_fmt_log2 ( uint32_t v)
static

log2 of a power-of-two value.

Loop-counted rather than a compiler builtin, so the host tests and every cross toolchain agree byte-for-byte. Bounded by the width of the input (NASA Rule 2).

Parameters
[in]vA power of two, >= 1.
Returns
log2(v).
Return values
0..31The shift that reproduces v.
Precondition
v is a power of two (callers validated it).
v is non-zero.
Postcondition
No state modified.
1U << result == v.
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 143 of file ra8_fs_fat_fmt.c.

Referenced by internal_fmt_fat32_default_spc().

◆ internal_fmt_seed_fats()

ra8_err_t internal_fmt_seed_fats ( const ra8_fs_backend_t * backend,
const ra8_fs_fmt_geom_t * g )
static

Seed the reserved FAT entries (and FAT32 root-cluster EOC) per copy.

Builds one zeroed FAT sector holding FAT[0] (media descriptor in the low byte, the rest 1-bits) and FAT[1] (a clean end-of-chain), plus – on FAT32 – FAT[2] marking the root cluster as a terminated single-cluster chain. The same first sector is written to the start of every FAT copy.

Parameters
[in]backendBlock-device backend.
[in]gResolved geometry.
Returns
Backend error code.
Return values
k_ra8_okAll FAT copies seeded.
k_ra8_err_*Backend write failure.
Precondition
backend, g are non-NULL.
g->fat_size_sectors and reserved_sectors are set.
Postcondition
FAT[0]/FAT[1] (and FAT[2] on FAT32) are valid in every copy.
g_fs_scratch holds the last FAT seed sector.
Note
Bounded loop (NASA Rule 2): k_fmt_num_fats iterations.
Since
0.1.0

Definition at line 509 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, ra8_fs_backend_t::ctx, ra8_fs_fmt_geom_t::fat_size_sectors, g_fs_scratch, k_byte_mask, k_cluster_eoc_min_fat16, k_cluster_eoc_min_fat32, k_cluster_eoc_write_fat16, k_cluster_eoc_write_fat32, k_fmt_media_fixed, k_fmt_num_fats, k_ra8_fs_type_fat16, k_ra8_fs_type_fat32, k_ra8_ok, priv_wr16(), priv_wr32(), ra8_fs_fmt_geom_t::reserved_sectors, ra8_fs_fmt_geom_t::type, and ra8_fs_backend_t::write_block.

Referenced by priv_fmt_emit_volume().

◆ internal_fmt_write_fsinfo()

ra8_err_t internal_fmt_write_fsinfo ( const ra8_fs_backend_t * backend,
const ra8_fs_fmt_geom_t * g,
const uint8_t * boot_sec )
static

Write the FAT32 FSInfo sector (and the backup boot sector copy).

Lays the FSInfo lead/struct/trail signatures and a best-effort free count + next-free hint, then copies the boot sector to the backup location. No-op for FAT12/16 (they have no FSInfo).

Parameters
[in]backendBlock-device backend.
[in]gResolved geometry (FAT32).
[in]boot_secThe freshly built boot sector to back up.
Returns
Backend error code.
Return values
k_ra8_okFSInfo + backup written (or nothing for FAT12/16).
k_ra8_err_*Backend write failure.
Precondition
backend, g, boot_sec are non-NULL.
g->type is FAT32 for any write to occur.
Postcondition
On FAT32, the FSInfo + backup-boot sectors are valid.
g_fs_scratch is clobbered.
Note
Not reentrant against the module scratch buffer.
Since
0.1.0

Definition at line 563 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, ra8_fs_fmt_geom_t::count_of_clusters, ra8_fs_backend_t::ctx, g_fs_scratch, k_fmt_bkboot_sector, k_fmt_fat32_nxt_free, k_fmt_fsi_lead_sig, k_fmt_fsi_off_free, k_fmt_fsi_off_lead, k_fmt_fsi_off_nxtfree, k_fmt_fsi_off_struct, k_fmt_fsi_off_trail, k_fmt_fsi_struct_sig, k_fmt_fsi_trail_sig, k_fmt_fsi_unknown, k_fmt_fsinfo_sector, k_ra8_fs_type_fat32, k_ra8_ok, priv_wr32(), ra8_fs_fmt_geom_t::type, and ra8_fs_backend_t::write_block.

Referenced by priv_fmt_emit_volume().

◆ internal_fmt_write_totals()

void internal_fmt_write_totals ( uint8_t * sec,
const ra8_fs_fmt_geom_t * g )
static

Write a totals/FAT-size pair into the BPB, choosing 16- vs 32-bit.

BPB_TotSec16/BPB_FATSz16 hold values that fit 16 bits; larger values spill to BPB_TotSec32/BPB_FATSz32 with the 16-bit field left zero (FAT12/16). FAT32 always uses the 32-bit fields. The caller passes the already-resolved type to drive that choice.

Parameters
[out]secBoot sector under construction.
[in]gGeometry with totals + FAT size.
Precondition
sec and g are non-NULL.
BPB common fields were already written.
Postcondition
The total-sectors and FAT-size BPB fields reflect g.
Exactly one width (16- or 32-bit) is non-zero per field.
Note
Not reentrant against the same buffer.
Since
0.1.0

Definition at line 311 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::fat_size_sectors, k_bpb_off_fat_sz_16, k_bpb_off_fat_sz_32, k_bpb_off_tot_sec_16, k_bpb_off_tot_sec_32, k_ra8_fs_type_fat32, k_word_mask, priv_wr16(), priv_wr32(), ra8_fs_fmt_geom_t::total_sectors, and ra8_fs_fmt_geom_t::type.

Referenced by internal_fmt_build_bpb_f16(), and internal_fmt_build_bpb_f32().

◆ internal_fmt_zero_run()

ra8_err_t internal_fmt_zero_run ( const ra8_fs_backend_t * backend,
uint64_t lba,
uint64_t count,
uint32_t bps )
static

Zero a run of sectors on the backend in multi-sector chunks.

Writes up to k_fmt_zero_chunk_bytes worth of sectors per write_block call from a read-only all-zero buffer, so an SD backend can clear the whole region with CMD25 multi-block writes instead of one slow CMD24 single-block write per sector (a 32 MB FAT on a 128 GB card drops from minutes to seconds). Bounds the loop by the caller's count.

Parameters
[in]backendBlock-device backend.
[in]lbaFirst sector to clear.
[in]countNumber of sectors to clear.
[in]bpsDevice sector size in bytes.
Returns
Backend error code (first failure aborts).
Return values
k_ra8_okAll count sectors zeroed.
k_ra8_err_*Backend write failure within the run.
Precondition
backend and backend->write_block are non-NULL.
lba + count does not exceed the device capacity.
Postcondition
On success, every byte in sectors lba .. lba+count-1 reads as zero.
On failure, sectors up to (but not including) the failing one may be zeroed.
Note
Bounded loop (NASA Rule 2): at most count iterations.
Since
0.1.0

Definition at line 453 of file ra8_fs_fat_fmt.c.

References ra8_fs_backend_t::ctx, k_fmt_zero_chunk_bytes, k_ra8_ok, s_fmt_zero_chunk, and ra8_fs_backend_t::write_block.

Referenced by priv_fmt_clear_region().

◆ priv_fmt_choose_geometry()

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.

Sweeps spc upward through powers of two (1, 2, 4, ... up to k_fmt_spc_max). For FAT32 the count shrinks with larger clusters, so the first spc whose count is in-band (or below k_fmt_fat32_clus_cap) wins. For FAT12/16 a too-large count fails the lower clusters and a too-small count fails the larger ones, so the sweep accepts the first in-band hit. When spc_hint is zero the starting point for FAT32 comes from priv_fmt_fat32_default_spc(); for FAT12/16 it starts at 1. On success the geometry's sectors_per_cluster, fat_size_sectors, and count_of_clusters are populated.

Parameters
[in,out]gGeometry with type, total_sectors, reserved_sectors, root_entries, and root_sectors pre-filled.
[in]spc_hintCaller-pinned cluster size (0 = auto-sweep).
Returns
Error code.
Return values
k_ra8_okGeometry chosen; output fields stored in g.
k_ra8_err_invalid_sizeNo cluster size yields a count in g->type's band.
Precondition
g is non-NULL with the input fields (type, total_sectors, reserved_sectors, root_entries, root_sectors) already set.
spc_hint is 0 or a power of two in the range [1, k_fmt_spc_max].
Postcondition
On k_ra8_ok, g->sectors_per_cluster, g->fat_size_sectors, and g->count_of_clusters are consistent and in-band for g->type.
On k_ra8_err_invalid_size, g is left partially written and must be discarded.
Note
Bounded loop (NASA Rule 2): at most k_fmt_spc_max+1 iterations.
Since
0.1.0

Definition at line 209 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, ra8_fs_fmt_geom_t::count_of_clusters, ra8_fs_fmt_geom_t::fat_size_sectors, internal_fmt_clusters_for(), internal_fmt_count_in_band(), internal_fmt_fat32_default_spc(), k_fmt_spc_max, k_ra8_err_invalid_size, k_ra8_fs_type_fat32, k_ra8_ok, ra8_fs_fmt_geom_t::sectors_per_cluster, ra8_fs_fmt_geom_t::total_sectors, and ra8_fs_fmt_geom_t::type.

Referenced by internal_format_locked().

◆ priv_fmt_clear_region()

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.

Tries backend->erase_blocks first: on flash media (SD) that erases a region internally in one operation, this avoids streaming tens of MB of zeros (~30 MB of FAT on a 128 GB FAT32 card). The erase path is only taken when the backend guarantees a zero read-back – it signals inability with k_ra8_err_not_supported, on which (or when no erase hook is bound) this falls back to priv_fmt_zero_run. Any other backend error aborts.

Parameters
[in]backendBlock-device backend.
[in]lbaFirst block to clear.
[in]countNumber of blocks to clear.
[in]bpsDevice sector size in bytes (sizes each zero write).
Returns
Error code.
Return values
k_ra8_okThe range now reads back as all-zero bytes.
k_ra8_err_*A backend write/erase failure (other than not_supported).
Precondition
backend is non-NULL with a non-NULL write_block.
count blocks starting at lba lie within the device.
bps is the device's real sector size (used to size each write).
Postcondition
On success [lba, lba+count) reads back as zero.
No metadata is written; caller seeds the FAT afterwards.
Note
Not thread-safe; part of single-threaded format.
MC/DC:
Decision: if ((erase_blocks != nullptr) && (erase_blocks(...) == k_ra8_ok)) (short-circuit AND). Erase is a pure optimization: any non-OK result (no hook, not_supported, a card that erases to ones, or a hardware error) falls through to the proven zero-write – so erase failure is never fatal. Vectors:
  • erase_blocks == NULL -> C1 false (short-circuit) -> zero-run.
  • erase_blocks returns k_ra8_ok -> C1 true, C2 true -> return ok (no zeroing).
  • erase_blocks returns non-ok -> C1 true, C2 false -> zero-run. (NULL,ok) prove C1 independence; (ok,non-ok) prove C2 independence.
Since
0.1.0

Definition at line 473 of file ra8_fs_fat_fmt.c.

References ra8_fs_backend_t::ctx, ra8_fs_backend_t::erase_blocks, internal_fmt_zero_run(), and k_ra8_ok.

Referenced by internal_exfat_write_bitmap(), internal_exfat_write_fat(), internal_exfat_write_root(), and priv_fmt_emit_volume().

◆ priv_fmt_emit_volume()

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.

The write phase of ra8_fs_format(), split out to keep the public entry under the NASA Rule 4 length budget. Clears the FAT + root region (bulk-erase or zero-write) first, then builds the type-specific BPB and persists it at LBA 0, seeds the FATs, and writes any FAT32 FSInfo + backup. The root region is left zero by the initial clear.

Parameters
[in]backendBlock-device backend.
[in]gResolved geometry.
[in]labelOptional volume label.
Returns
Error code.
Return values
k_ra8_okVolume image fully written.
k_ra8_err_*Backend write failure mid-format.
Precondition
backend, g are non-NULL with geometry resolved.
g->type is FAT12/FAT16/FAT32.
Postcondition
On success the device holds a mountable g->type volume.
On failure the device may be partially written.
Note
Not thread-safe; serialise with mounts on the same backend.
Since
0.1.0

Definition at line 602 of file ra8_fs_fat_fmt.c.

References ra8_fs_fmt_geom_t::bytes_per_sector, ra8_fs_backend_t::ctx, ra8_fs_fmt_geom_t::fat_size_sectors, internal_fmt_build_bpb_f16(), internal_fmt_build_bpb_f32(), internal_fmt_seed_fats(), internal_fmt_write_fsinfo(), k_fmt_num_fats, k_ra8_fs_type_fat32, k_ra8_ok, priv_byte_fill(), priv_fmt_clear_region(), priv_sec_walk(), ra8_fs_fmt_geom_t::reserved_sectors, ra8_fs_fmt_geom_t::root_sectors, ra8_fs_fmt_geom_t::sectors_per_cluster, ra8_fs_fmt_geom_t::type, and ra8_fs_backend_t::write_block.

Referenced by internal_format_locked().

◆ priv_fmt_label_field()

void priv_fmt_label_field ( uint8_t * dst,
const char * label )

Pad an ASCII volume label into an 11-byte BS_VolLab / label field.

Copies label up to its NUL (or 11 characters) then space-fills the remainder, matching the BS_VolLab convention. A NULL or empty label resolves to the FAT specification's unlabelled sentinel "NO NAME " – never zeros and never a bare run of spaces, both of which fsck.fat treats as a corrupt label and strips (#634). Shared by the formatter (ra8_fs_format()) and the runtime label writer (ra8_fs_set_label()), so both lay the field identically.

Parameters
[out]dstDestination 11-byte label field.
[in]labelSource label, or NULL / "" for the unlabelled sentinel.
Returns
Nothing.
Precondition
dst is non-NULL and addresses at least k_fmt_label_len bytes.
label is NUL-terminated when non-NULL.
Postcondition
dst holds the padded 11-byte label (or the "NO NAME " sentinel).
No byte past offset 10 of dst is touched.
Note
Bounded loop (NASA Rule 2): exactly k_fmt_label_len iterations.
Since
0.1.0

Definition at line 272 of file ra8_fs_fat_fmt.c.

References k_fmt_label_len.

Referenced by internal_fat_boot_set_label(), internal_fat_put_vol_id(), internal_fmt_build_bpb_f16(), and internal_fmt_build_bpb_f32().

◆ priv_fmt_reserved_for()

uint32_t priv_fmt_reserved_for ( ra8_fs_type_t type)

Map a requested FAT type to its reserved-sector count.

FAT32 reserves a 32-sector region (boot + FSInfo + backup); FAT12/16 reserve only the single boot sector.

Parameters
[in]typeRequested FAT variant.
Returns
Reserved-sector count for type.
Return values
k_fmt_resv_f32type is FAT32.
k_fmt_resv_f16type is FAT12 or FAT16.
Precondition
type is one of FAT12/FAT16/FAT32.
Caller has rejected exFAT/unknown beforehand.
Postcondition
No state modified.
Result is purely a function of type.
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 27 of file ra8_fs_fat_fmt.c.

References k_fmt_resv_f16, k_fmt_resv_f32, and k_ra8_fs_type_fat32.

Referenced by internal_format_locked().

◆ priv_fmt_spc_valid()

bool priv_fmt_spc_valid ( uint8_t spc)

Validate a caller-pinned sectors-per-cluster value.

A zero value defers to the auto-sweep. A non-zero value must be a power of two in the closed range 1..k_fmt_spc_max.

Parameters
[in]spcRequested cluster size.
Returns
Whether spc is acceptable.
Return values
truespc is 0 (auto) or a power of two in 1..128.
falsespc is non-zero and not a valid power of two.
Precondition
None (total function over uint8_t).
Caller treats false as k_ra8_err_invalid_arg.
Postcondition
No state modified.
Result is purely a function of spc.
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 589 of file ra8_fs_fat_fmt.c.

References k_fmt_spc_max.

Referenced by internal_format_locked().

Variable Documentation

◆ s_fmt_zero_chunk

const uint8_t s_fmt_zero_chunk[k_fmt_zero_chunk_bytes] = {}
static

All-zero source for the chunked FAT/root wipe (read-only, in flash).

Definition at line 421 of file ra8_fs_fat_fmt.c.

Referenced by internal_fmt_zero_run().