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

Read-only consistency check (fsck): the exFAT half. More...

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

Go to the source code of this file.

Data Structures

struct  exfat_dir_stack_t
 Bounded worklist of exFAT directories still to walk (NASA P10 Rule 1). More...

Enumerations

enum  ra8_fs_exfat_check_const_t : uint32_t {
  k_exchk_bits_per_byte = 8U ,
  k_exchk_bit_mask = 7U ,
  k_exchk_byte_shift = 3U
}
 Bit-arithmetic constants for the exFAT allocation-bitmap diff. More...

Functions

static uint32_t internal_exchk_popcount8 (uint8_t b)
 Count the set bits in one byte (portable, no compiler builtin).
static void internal_exchk_mark_run (ra8_fs_check_ctx_t *ctx, uint32_t first, uint64_t nclus)
 Mark a contiguous cluster run visited, detecting cross-links.
void ra8_fs_check_test_exfat_mark_run (ra8_fs_check_ctx_t *ctx, uint32_t first, uint64_t nclus)
 Exercise the exFAT contiguous-run marker from a host unit test.
static ra8_err_t internal_exchk_mark_fatchain (ra8_fs_check_ctx_t *ctx, uint32_t first)
 Mark a FAT-chained file's whole chain visited, detecting cross-links.
ra8_err_t ra8_fs_check_test_exfat_mark_fatchain (ra8_fs_check_ctx_t *ctx, uint32_t first)
 Exercise the exFAT fragmented-chain walker from a host unit test.
static ra8_err_t internal_exchk_mark_dir_alloc (ra8_fs_check_ctx_t *ctx, const exfat_dir_t *dir)
 Mark a directory's own cluster allocation visited.
ra8_err_t ra8_fs_check_test_exfat_mark_dir_alloc (ra8_fs_check_ctx_t *ctx, uint32_t first)
 Exercise the exFAT FAT-chained directory allocation marker from a host test.
static void internal_exchk_system_run (ra8_fs_check_ctx_t *ctx, const uint8_t *e)
 Mark the clusters a bitmap (0x81) or up-case (0x82) system entry owns.
static void internal_exchk_extract_name (const uint8_t *set, uint32_t nlen, uint16_t *units)
 Extract a File entry set's name into UTF-16 units for hashing.
static void internal_exchk_verify_set (ra8_fs_check_ctx_t *ctx, const uint8_t *set, uint32_t count, uint64_t lba, uint32_t off)
 Verify a gathered entry set's SetChecksum and NameHash.
static void internal_exchk_push (ra8_fs_check_ctx_t *ctx, exfat_dir_stack_t *stack, const exfat_dir_t *dir)
 Push an exFAT subdirectory onto the walk stack, capping the depth.
void ra8_fs_check_test_exfat_push_overflow (ra8_fs_check_ctx_t *ctx, uint32_t cluster, bool already_truncated)
 Exercise the exFAT directory-worklist overflow guard from a host test.
static ra8_err_t internal_exchk_set_clusters (ra8_fs_check_ctx_t *ctx, const uint8_t *set, const uint8_t *file, exfat_dir_stack_t *stack, uint64_t lba, uint32_t off)
 Validate a verified entry set's first cluster and mark or queue it.
static ra8_err_t internal_exchk_set (ra8_fs_check_ctx_t *ctx, exfat_cursor_t *cur, const uint8_t *file, exfat_dir_stack_t *stack)
 Gather and process one File entry set: verify it, then mark or queue it.
static ra8_err_t internal_exchk_scan_dir_file_entry (ra8_fs_check_ctx_t *ctx, exfat_cursor_t *cur, const uint8_t *e, exfat_dir_stack_t *stack, uint32_t dir_cluster, bool *out_stop)
 Dispatch one live File entry: truncation-checked, then set-verified.
static ra8_err_t internal_exchk_scan_dir_terminal (ra8_fs_check_ctx_t *ctx, exfat_cursor_t *cur, const exfat_dir_t *dir)
 Probe exactly one entry past the scan ceiling to classify the walk.
static ra8_err_t internal_exchk_scan_dir (ra8_fs_check_ctx_t *ctx, const exfat_dir_t *dir, exfat_dir_stack_t *stack)
 Walk one exFAT directory, verifying and marking every live entry.
static ra8_err_t internal_exchk_tree (ra8_fs_check_ctx_t *ctx)
 Walk the whole exFAT directory tree from the root with a worklist.
static void internal_exchk_diff_byte (ra8_fs_check_ctx_t *ctx, uint8_t b, uint32_t base)
 Diff one allocation-bitmap byte against the visited bitmap.
static ra8_err_t internal_exchk_bitmap_pass (ra8_fs_check_ctx_t *ctx, uint64_t bmp_lba)
 Read the allocation bitmap: count used / free, and diff if referencing.
ra8_err_t priv_check_exfat (ra8_fs_check_ctx_t *ctx)
 Run the exFAT consistency check into the context's report.

Detailed Description

Read-only consistency check (fsck): the exFAT half.

The exFAT side of ra8_fs_check, sharing the scaffolding in ra8_fs_fat_check.c (the finding recorder and the visited-cluster bitmap). exFAT makes the allocation bitmap the sole authority on which clusters are in use (exFAT spec sec 7.1), so the check has a different shape from the FAT one:

  1. Walk the directory tree, from the root, marking in the caller's scratch bitmap every cluster anything references – each file's data run, each directory's own run, and the three system runs (the allocation bitmap, the up-case table, the root directory). Every File entry set is verified as it is walked: its SetChecksum must recompute to the stored value, and its Stream entry's NameHash must recompute to the stored one.
  2. Diff against the allocation bitmap, in BOTH directions: a bit the bitmap sets that nothing referenced is a lost cluster, and a cluster something referenced whose bit is clear is a bitmap mismatch.

With no scratch bitmap supplied the walk is skipped and the pass reports only the allocation bitmap's own used / free population count.

References (every shorthand citation in this file):

  • "exFAT spec" = Microsoft Corp., "exFAT file system specification", revision 1.00, March 2021. Entry sets are sec 6; the allocation bitmap sec 7.1; the checksums sec 6.3.3 (SetChecksum) and 7.5 (NameHash).

NASA Power-of-Ten compliance:

  • Rule 1: the directory tree is walked with an explicit worklist, never recursion.
  • Rule 2: every cluster walk is bounded by count_of_clusters and cut short by the visited bitmap; the entry walk by k_exfat_scan_limit; the worklist depth by k_ra8_fs_check_max_dirs.
  • Rule 3: zero malloc; the visited bitmap is caller-supplied, the worklist a bounded stack.
  • Rule 7: every backend call is checked.
Since
0.1.0

Definition in file ra8_fs_fat_exfat_check.c.

Enumeration Type Documentation

◆ ra8_fs_exfat_check_const_t

enum ra8_fs_exfat_check_const_t : uint32_t

Bit-arithmetic constants for the exFAT allocation-bitmap diff.

The allocation bitmap packs one cluster per bit, LSB first, exactly like the visited bitmap the check marks, so cluster index >> 3 is a byte and & 7 is a bit – and the two can be compared bit for bit.

Since
0.1.0
Enumerator
k_exchk_bits_per_byte 

Bits in one allocation-bitmap byte.

k_exchk_bit_mask 

Cluster index -> bit within its byte.

k_exchk_byte_shift 

log2(8): cluster index -> bitmap byte.

Definition at line 63 of file ra8_fs_fat_exfat_check.c.

Function Documentation

◆ internal_exchk_bitmap_pass()

ra8_err_t internal_exchk_bitmap_pass ( ra8_fs_check_ctx_t * ctx,
uint64_t bmp_lba )
static

Read the allocation bitmap: count used / free, and diff if referencing.

Streams the allocation bitmap sector by sector (masking the tail byte to the last cluster), summing the set bits into clusters_used and, when a visited bitmap is present, diffing every bit against it.

Parameters
[in,out]ctxThe scan context.
[in]bmp_lbaFirst (volume-relative) LBA of the allocation bitmap.
Returns
Error code.
Return values
k_ra8_okThe bitmap was read.
k_ra8_err_*Backend read failure.
Precondition
ctx is non-NULL; bmp_lba locates the allocation bitmap.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
clusters_used + clusters_free == clusters_total.
In reference mode, clusters_lost / bitmap_mismatches are populated.
Note
Bounded loop (NASA Rule 2): clusters_total / 8 + 1 bytes.
Since
0.1.0

Definition at line 865 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_ctx_t::bitmap, ra8_fs_check_report_t::clusters_free, ra8_fs_check_report_t::clusters_total, ra8_fs_check_report_t::clusters_used, internal_exchk_diff_byte(), internal_exchk_popcount8(), k_exchk_bit_mask, k_exchk_byte_shift, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_bps(), priv_read_sector(), priv_sec_io(), and ra8_fs_check_ctx_t::rep.

Referenced by priv_check_exfat().

◆ internal_exchk_diff_byte()

void internal_exchk_diff_byte ( ra8_fs_check_ctx_t * ctx,
uint8_t b,
uint32_t base )
static

Diff one allocation-bitmap byte against the visited bitmap.

For each of the byte's clusters: allocated-but-unvisited is a lost cluster, and visited-but-unallocated is a bitmap mismatch. Run only in the reference mode; the population count is done by the caller.

Parameters
[in,out]ctxThe scan context.
[in]bThe (tail-masked) allocation-bitmap byte.
[in]baseCluster index of bit 0 of b.
Returns
Nothing.
Precondition
ctx and its bitmap are non-NULL.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
clusters_lost and bitmap_mismatches reflect this byte's disagreements.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): k_exchk_bits_per_byte iterations.
Since
0.1.0

Definition at line 811 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_ctx_t::bitmap, ra8_fs_check_report_t::bitmap_mismatches, ra8_fs_check_report_t::clusters_lost, ra8_fs_check_report_t::clusters_total, k_cluster_first_data, k_exchk_bit_mask, k_exchk_bits_per_byte, k_exchk_byte_shift, k_ra8_fs_check_fault_bitmap_ref_unset, k_ra8_fs_check_fault_lost_cluster, priv_check_fault(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_bitmap_pass().

◆ internal_exchk_extract_name()

void internal_exchk_extract_name ( const uint8_t * set,
uint32_t nlen,
uint16_t * units )
static

Extract a File entry set's name into UTF-16 units for hashing.

Reads nlen units out of the Name (0xC1) entries, which begin at the third entry of the set (byte offset 64) and pack 15 units each.

Parameters
[in]setThe gathered entry-set bytes.
[in]nlenName length in UTF-16 units (clamped to k_exfat_name_cap).
[out]unitsReceives nlen UTF-16 code units.
Returns
Nothing.
Precondition
set and units are non-NULL; nlen <= k_exfat_name_cap.
set holds the File + Stream + Name entries.
Postcondition
units[0..nlen) mirror the on-disk name.
No state outside units is touched.
Note
Bounded loop (NASA Rule 2): nlen (<= 64) iterations.
Since
0.1.0

Definition at line 346 of file ra8_fs_fat_exfat_check.c.

References k_exfat_entry_bytes, k_exfat_name_off, k_exfat_name_per_entry, and priv_rd16().

Referenced by internal_exchk_verify_set().

◆ internal_exchk_mark_dir_alloc()

ra8_err_t internal_exchk_mark_dir_alloc ( ra8_fs_check_ctx_t * ctx,
const exfat_dir_t * dir )
static

Mark a directory's own cluster allocation visited.

Walks the directory's run (contiguous or FAT-chained, decided by dir->contig_end) with priv_exfat_step_cluster, marking each cluster – so a directory whose contents stop at an early end-of-directory marker still has its trailing allocated clusters counted as referenced, which the entry walk alone would miss. A successor remaining after the last permitted hop is validated as a cross-link or bad entry.

Parameters
[in,out]ctxThe scan context.
[in]dirThe directory whose allocation is marked.
Returns
Error code.
Return values
k_ra8_okThe allocation was marked (a fault may have been recorded).
k_ra8_err_*Backend read failure.
Precondition
ctx and its bitmap are non-NULL; dir->cluster is a heap cluster.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
Every cluster of the directory's run up to the first fault is marked.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): clusters_total hops, bitmap-terminated.
Since
0.1.0

Definition at line 257 of file ra8_fs_fat_exfat_check.c.

References exfat_dir_t::cluster, ra8_fs_check_report_t::clusters_total, exfat_dir_t::contig_end, k_ra8_err_not_found, k_ra8_fs_check_fault_bad_dir_entry, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_check_visit(), priv_exfat_step_cluster(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_tree(), and ra8_fs_check_test_exfat_mark_dir_alloc().

◆ internal_exchk_mark_fatchain()

ra8_err_t internal_exchk_mark_fatchain ( ra8_fs_check_ctx_t * ctx,
uint32_t first )
static

Mark a FAT-chained file's whole chain visited, detecting cross-links.

A file whose run fragmented carries a real FAT chain instead of NoFatChain; this follows it, marking each cluster and flagging a revisit (cross-link) or a next-cluster out of range (bad chain). A non-terminal successor after exactly clusters_total visits is checked once more, which necessarily exposes a revisit or bad tail.

Parameters
[in,out]ctxThe scan context.
[in]firstThe file's first cluster (in range).
Returns
Error code.
Return values
k_ra8_okThe chain was walked (a fault may have been recorded).
k_ra8_err_*Backend read failure.
Precondition
ctx and its bitmap are non-NULL; first is in range.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
Every cluster of the chain up to the first fault is marked.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): clusters_total hops, bitmap-terminated.
Since
0.1.0

Definition at line 199 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_report_t::clusters_total, k_ra8_fs_check_fault_bad_chain, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_check_fault(), priv_check_in_range(), priv_check_visit(), priv_fat_get(), priv_is_eoc(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_set_clusters(), and ra8_fs_check_test_exfat_mark_fatchain().

◆ internal_exchk_mark_run()

void internal_exchk_mark_run ( ra8_fs_check_ctx_t * ctx,
uint32_t first,
uint64_t nclus )
static

Mark a contiguous cluster run visited, detecting cross-links.

Used for a NoFatChain file and for the bitmap / up-case system runs. A cluster already visited is a cross-link; a cluster out of range is a bad entry. A run longer than the in-volume suffix starting at first is faulted before the bounded in-range prefix is marked, so clamping a corrupt DataLength can never turn it into a clean run.

Parameters
[in,out]ctxThe scan context.
[in]firstFirst cluster of the run.
[in]nclusCluster count of the run.
Returns
Nothing.
Precondition
ctx and its bitmap are non-NULL.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
Every in-range cluster of the run up to the first fault is marked.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): capped at clusters_total iterations.
Since
0.1.0

Definition at line 146 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_report_t::clusters_total, ra8_fs_check_report_t::entries_bad, k_cluster_first_data, k_ra8_fs_check_fault_bad_dir_entry, priv_check_fault(), priv_check_in_range(), priv_check_visit(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_set_clusters(), internal_exchk_system_run(), and ra8_fs_check_test_exfat_mark_run().

◆ internal_exchk_popcount8()

uint32_t internal_exchk_popcount8 ( uint8_t b)
static

Count the set bits in one byte (portable, no compiler builtin).

A bounded eight-iteration bit count, so the result is identical on the host and on the target.

Parameters
[in]bByte to count.
Returns
The number of 1 bits in b.
Return values
0..8The population count.
Precondition
None (total over uint8_t).
b is a whole byte.
Postcondition
No state modified.
Result is at most 8.
Note
Pure; trivially thread-safe.
Bounded loop (NASA Rule 2): exactly k_exchk_bits_per_byte iterations.
Since
0.1.0

Definition at line 107 of file ra8_fs_fat_exfat_check.c.

References k_exchk_bits_per_byte.

Referenced by internal_exchk_bitmap_pass().

◆ internal_exchk_push()

void internal_exchk_push ( ra8_fs_check_ctx_t * ctx,
exfat_dir_stack_t * stack,
const exfat_dir_t * dir )
static

Push an exFAT subdirectory onto the walk stack, capping the depth.

Guards the directory worklist against overflow, recording one truncation fault.

Parameters
[in,out]ctxThe scan context (for the truncation fault).
[in,out]stackThe directory worklist.
[in]dirThe subdirectory to queue.
Returns
Nothing.
Precondition
ctx, stack are non-NULL.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
The subdirectory is queued, or dropped with a one-time truncation fault.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 434 of file ra8_fs_fat_exfat_check.c.

References exfat_dir_t::cluster, exfat_dir_stack_t::items, k_ra8_fs_check_fault_scan_truncated, k_ra8_fs_check_max_dirs, priv_check_fault(), exfat_dir_stack_t::top, and exfat_dir_stack_t::truncated.

Referenced by internal_exchk_set_clusters(), and ra8_fs_check_test_exfat_push_overflow().

◆ internal_exchk_scan_dir()

ra8_err_t internal_exchk_scan_dir ( ra8_fs_check_ctx_t * ctx,
const exfat_dir_t * dir,
exfat_dir_stack_t * stack )
static

Walk one exFAT directory, verifying and marking every live entry.

Iterates a directory entry stream, dispatching system, file and directory sets. At the entry ceiling it performs one terminal probe: an exhausted allocation or immediate end marker is a valid exact-bound directory, while another live or deleted entry records scan truncation.

Parameters
[in,out]ctxThe scan context.
[in]dirThe directory to walk.
[in,out]stackThe directory worklist.
Returns
Error code.
Return values
k_ra8_okThe directory was walked.
k_ra8_err_*Backend read failure.
Precondition
Every pointer is non-NULL; the mount is exFAT.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
Every referenced cluster it names is marked; every set it holds verified.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): k_exfat_scan_limit entries.
Since
0.1.0

Definition at line 705 of file ra8_fs_fat_exfat_check.c.

References exfat_dir_t::cluster, internal_exchk_scan_dir_file_entry(), internal_exchk_scan_dir_terminal(), internal_exchk_system_run(), k_exfat_entry_bitmap, k_exfat_entry_bytes, k_exfat_entry_eod, k_exfat_entry_file, k_exfat_entry_upcase, k_exfat_inuse_bit, k_exfat_scan_limit, k_ra8_err_not_found, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_exfat_cursor_init(), priv_exfat_next_entry(), and exfat_cursor_t::scanned.

Referenced by internal_exchk_tree().

◆ internal_exchk_scan_dir_file_entry()

ra8_err_t internal_exchk_scan_dir_file_entry ( ra8_fs_check_ctx_t * ctx,
exfat_cursor_t * cur,
const uint8_t * e,
exfat_dir_stack_t * stack,
uint32_t dir_cluster,
bool * out_stop )
static

Dispatch one live File entry: truncation-checked, then set-verified.

A File entry's SecondaryCount declares how many more stream/name entries follow as one set. When that count would run past the scan ceiling, the walk is a truncation, not a malformed set, and is reported and stopped here rather than inside set assembly. Otherwise the full set is read and verified through internal_exchk_set.

Parameters
[in,out]ctxThe scan context.
[in,out]curCursor positioned just past the File entry itself.
[in]eThe just-read File entry bytes.
[in,out]stackDirectory worklist for referenced subdirectories.
[in]dir_clusterCluster of the directory being scanned, for the truncation fault report.
[out]out_stopWhether the caller's scan loop must return immediately with the returned status.
Returns
Status to return from the scan loop when out_stop is true; k_ra8_ok (continue scanning) when false.
Return values
k_ra8_okThe set fit and verified, or a truncation was reported.
k_ra8_err_*Backend read failure while assembling the set.
Precondition
ctx, cur, e, stack, and out_stop are non-NULL.
cur->scanned is at most k_exfat_scan_limit, so the remaining count cannot wrap.
Postcondition
out_stop is always written.
No volume state is modified; only ctx counters, faults, and cur advance.
Note
Bounded by the caller's scan ceiling (NASA Rule 2).
Since
0.1.0

Definition at line 620 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_set(), k_exfat_off_file_secnt, k_exfat_scan_limit, k_exfat_set_max_entries, k_ra8_fs_check_fault_scan_truncated, k_ra8_ok, priv_check_fault(), and exfat_cursor_t::scanned.

Referenced by internal_exchk_scan_dir().

◆ internal_exchk_scan_dir_terminal()

ra8_err_t internal_exchk_scan_dir_terminal ( ra8_fs_check_ctx_t * ctx,
exfat_cursor_t * cur,
const exfat_dir_t * dir )
static

Probe exactly one entry past the scan ceiling to classify the walk.

An exhausted allocation or an immediate end-of-directory marker proves the directory ended exactly on the scan bound; any other live or deleted entry proves the walk was truncated.

Parameters
[in,out]ctxThe scan context.
[in,out]curCursor positioned at the scan ceiling.
[in]dirThe directory being scanned, for the truncation fault report.
Returns
Error code.
Return values
k_ra8_okThe directory ended exactly at the bound, or a truncation was reported.
k_ra8_err_*Backend read failure.
Precondition
ctx, cur, and dir are non-NULL.
cur has already reached the scan ceiling, so this is the classifying probe.
Postcondition
No volume state is modified.
At most one further directory entry is consumed from cur.
Note
Exactly one bounded read (NASA Rule 2).
Since
0.1.0

Definition at line 663 of file ra8_fs_fat_exfat_check.c.

References exfat_dir_t::cluster, k_exfat_entry_bytes, k_exfat_entry_eod, k_ra8_err_not_found, k_ra8_fs_check_fault_scan_truncated, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_check_fault(), and priv_exfat_next_entry().

Referenced by internal_exchk_scan_dir().

◆ internal_exchk_set()

ra8_err_t internal_exchk_set ( ra8_fs_check_ctx_t * ctx,
exfat_cursor_t * cur,
const uint8_t * file,
exfat_dir_stack_t * stack )
static

Gather and process one File entry set: verify it, then mark or queue it.

Reads the whole set from cur (advancing it past the set), verifies its SetChecksum and NameHash, validates its first cluster, and then either marks a file's clusters (contiguous or FAT-chained) or queues a subdirectory to be walked. A SecondaryCount outside the writable range is a malformed set: it is faulted and skipped, and the leftover secondary entries the outer walk then sees are ignored as non-File types.

Parameters
[in,out]ctxThe scan context.
[in,out]curThe directory cursor, positioned just after the File entry.
[in]fileThe 32-byte File (0x85) entry.
[in,out]stackThe directory worklist.
Returns
Error code.
Return values
k_ra8_okThe set was processed (faults may have been recorded).
k_ra8_err_*Backend read failure.
Precondition
Every pointer is non-NULL; file is a 0x85 entry.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
A valid file's clusters are marked; a directory is queued.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 560 of file ra8_fs_fat_exfat_check.c.

References exfat_cursor_t::cluster, ra8_fs_check_report_t::entries_bad, exfat_cursor_t::entry_in_cluster, internal_exchk_set_clusters(), internal_exchk_verify_set(), k_exfat_entry_bytes, k_exfat_off_file_secnt, k_exfat_set_max_entries, k_ra8_err_not_found, k_ra8_fs_check_fault_bad_dir_entry, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_bps(), priv_byte_copy(), priv_check_fault(), priv_cluster_to_lba(), priv_exfat_next_entry(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_scan_dir_file_entry().

◆ internal_exchk_set_clusters()

ra8_err_t internal_exchk_set_clusters ( ra8_fs_check_ctx_t * ctx,
const uint8_t * set,
const uint8_t * file,
exfat_dir_stack_t * stack,
uint64_t lba,
uint32_t off )
static

Validate a verified entry set's first cluster and mark or queue it.

The cluster half of ::priv_exchk_set, split out to keep both inside the function-size gate. Reads the Stream entry, validates the first cluster, then counts an empty file, records an out-of-range entry, queues a subdirectory, or marks a file's run (contiguous or chained).

Parameters
[in,out]ctxThe scan context.
[in]setThe gathered entry-set bytes (File + Stream + Name).
[in]fileThe 32-byte File (0x85) entry.
[in,out]stackThe directory worklist.
[in]lbaVolume-relative sector the File entry was read from.
[in]offByte offset of the File entry in that sector.
Returns
Error code.
Return values
k_ra8_okThe entry was processed (faults may have been recorded).
k_ra8_err_*Backend read failure marking a FAT-chained file.
Precondition
Every pointer is non-NULL; set holds a verified entry set.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
A valid file's clusters are marked; a directory is queued.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 491 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_report_t::entries_bad, ra8_fs_check_report_t::files_visited, internal_exchk_mark_fatchain(), internal_exchk_mark_run(), internal_exchk_push(), k_exfat_attr_directory, k_exfat_entry_bytes, k_exfat_off_file_attr, k_exfat_secflag_no_fat, k_exfat_strm_off_clus, k_exfat_strm_off_dlen, k_exfat_strm_off_flags, k_ra8_fs_check_fault_bad_dir_entry, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_check_fault(), priv_check_in_range(), priv_cluster_bytes(), priv_exfat_dir_from_set(), priv_rd32(), priv_rd64(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_set().

◆ internal_exchk_system_run()

void internal_exchk_system_run ( ra8_fs_check_ctx_t * ctx,
const uint8_t * e )
static

Mark the clusters a bitmap (0x81) or up-case (0x82) system entry owns.

Both system entries carry FirstCluster and DataLength in the same fields a Stream entry uses, so the run is ceil(DataLength / cluster bytes) clusters from FirstCluster.

Parameters
[in,out]ctxThe scan context.
[in]eThe 32-byte system directory entry.
Returns
Nothing.
Precondition
ctx and its bitmap are non-NULL; e is a 0x81 or 0x82 entry.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
The system run is marked referenced.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 307 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_mark_run(), k_exfat_strm_off_clus, k_exfat_strm_off_dlen, ra8_fs_check_ctx_t::m, priv_cluster_bytes(), priv_rd32(), and priv_rd64().

Referenced by internal_exchk_scan_dir().

◆ internal_exchk_tree()

ra8_err_t internal_exchk_tree ( ra8_fs_check_ctx_t * ctx)
static

Walk the whole exFAT directory tree from the root with a worklist.

Pops directories off the worklist, marking each and scanning its entries.

Parameters
[in,out]ctxThe scan context.
Returns
Error code.
Return values
k_ra8_okThe tree was walked (faults may have been recorded).
k_ra8_err_*Backend read failure.
Precondition
ctx and its bitmap are non-NULL; the mount is exFAT.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
Every referenced cluster is marked; every entry set verified.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): at most k_ra8_fs_check_max_dirs pops.
Since
0.1.0

Definition at line 757 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_report_t::dirs_visited, internal_exchk_mark_dir_alloc(), internal_exchk_scan_dir(), exfat_dir_stack_t::items, k_ra8_fs_check_max_dirs, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_exfat_dir_root(), ra8_fs_check_ctx_t::rep, and exfat_dir_stack_t::top.

Referenced by priv_check_exfat().

◆ internal_exchk_verify_set()

void internal_exchk_verify_set ( ra8_fs_check_ctx_t * ctx,
const uint8_t * set,
uint32_t count,
uint64_t lba,
uint32_t off )
static

Verify a gathered entry set's SetChecksum and NameHash.

Recomputes both from the set's own bytes and compares to the stored values – the two integrity fields exFAT keeps over an entry set – recording a fault for each mismatch. The name is clamped to the driver's name cap for the hash extraction; a longer foreign name still has its checksum verified over the full set.

Parameters
[in,out]ctxThe scan context.
[in]setThe gathered entry-set bytes (File + Stream + Name).
[in]countEntry count of the set.
[in]lbaVolume-relative sector the File entry was read from.
[in]offByte offset of the File entry in that sector.
Returns
Nothing.
Precondition
ctx and set are non-NULL; 2 <= count <= k_exfat_set_max_entries.
No filesystem operation runs concurrently on the mount (single-threaded by contract).
Postcondition
A SetChecksum or NameHash mismatch raises a fault and bumps entries_bad.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 384 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_report_t::entries_bad, internal_exchk_extract_name(), k_exfat_entry_bytes, k_exfat_name_cap, k_exfat_off_file_csum, k_exfat_off_strm_hash, k_exfat_strm_off_nlen, k_ra8_fs_check_fault_bad_name_hash, k_ra8_fs_check_fault_bad_set_checksum, priv_check_fault(), priv_exfat_name_hash(), priv_exfat_set_checksum(), priv_rd16(), and ra8_fs_check_ctx_t::rep.

Referenced by internal_exchk_set().

◆ priv_check_exfat()

ra8_err_t priv_check_exfat ( ra8_fs_check_ctx_t * ctx)

Run the exFAT consistency check into the context's report.

The exFAT-side dispatch of ra8_fs_check: verifies each entry set's SetChecksum and NameHash, marks every referenced cluster (files, directories and the bitmap / up-case system runs), and diffs that against the allocation bitmap in both directions. Defined in ra8_fs_fat_exfat_check.c.

Parameters
[in,out]ctxThe scan context (ctx->m->type is exFAT).
Returns
Error code.
Return values
k_ra8_okThe scan completed; findings are in the report.
k_ra8_err_*Backend read failure mid-scan.
Precondition
ctx is non-NULL; ctx->m->type is exFAT.
The mount is in use and its geometry is populated.
Postcondition
On k_ra8_ok the report's counts and faults describe the volume.
No volume state is modified.
Note
Not thread-safe; the check holds the library lock.
Since
0.1.0

Definition at line 898 of file ra8_fs_fat_exfat_check.c.

References ra8_fs_check_ctx_t::bitmap, ra8_fs_check_report_t::entries_bad, internal_exchk_bitmap_pass(), internal_exchk_tree(), k_ra8_err_not_found, k_ra8_fs_check_fault_bad_dir_entry, k_ra8_ok, ra8_fs_check_ctx_t::m, priv_check_fault(), priv_check_zero_bitmap(), priv_cluster_to_lba(), priv_exfat_find_bitmap(), and ra8_fs_check_ctx_t::rep.

◆ ra8_fs_check_test_exfat_mark_dir_alloc()

ra8_err_t ra8_fs_check_test_exfat_mark_dir_alloc ( ra8_fs_check_ctx_t * ctx,
uint32_t first )

Exercise the exFAT FAT-chained directory allocation marker from a host test.

Builds a synthetic FAT-chained directory descriptor around first and marks its allocation without scanning directory entries. This isolates the allocation walk's exact hop ceiling from the entry scanner. Production code must call ra8_fs_check().

Parameters
[in,out]ctxSynthetic scan context whose mount supplies the FAT.
[in]firstFirst cluster of the synthetic directory chain.
Returns
Error code.
Return values
k_ra8_okThe allocation was walked; findings are in the report.
k_ra8_err_*Backend read failure.
Precondition
ctx, its report, bitmap and mount are non-NULL.
ctx->rep->clusters_total is non-zero and first is in range.
Postcondition
Every traversed cluster is marked, up to the first finding.
A non-terminal successor after the final hop records a cross-link or bad-directory fault.
Note
Test-only and not thread-safe; no filesystem lock is acquired.
MC/DC:
Host vectors independently provide EOC and an in-range cycle after the exact hop bound.
Since
0.1.0

Definition at line 279 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_mark_dir_alloc().

◆ ra8_fs_check_test_exfat_mark_fatchain()

ra8_err_t ra8_fs_check_test_exfat_mark_fatchain ( ra8_fs_check_ctx_t * ctx,
uint32_t first )

Exercise the exFAT fragmented-chain walker from a host unit test.

Exposes the otherwise file-local bounded walker so the exact clusters_total boundary can be driven without constructing an impossible public volume in which one file owns every cluster also needed by the root directory and allocation bitmap. Production code must call ra8_fs_check(), never this test seam.

Parameters
[in,out]ctxSynthetic scan context whose mount supplies the FAT.
[in]firstFirst cluster of the synthetic fragmented chain.
Returns
Error code.
Return values
k_ra8_okThe chain was walked; consistency findings are in the report.
k_ra8_err_*Backend read failure.
Precondition
ctx, its report, bitmap and mount are non-NULL.
ctx->rep->clusters_total is non-zero and first is in range.
Postcondition
Every traversed cluster is marked, up to the first consistency finding.
A non-terminal successor after the final bounded hop records a specific cross-link or bad-chain finding.
Note
Test-only and not thread-safe; no filesystem lock is acquired.
MC/DC:
The host vectors independently select an end-of-chain marker, an in-range cycle, and an out-of-range tail after the exact hop bound.
Since
0.1.0

Definition at line 225 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_mark_fatchain().

◆ ra8_fs_check_test_exfat_mark_run()

void ra8_fs_check_test_exfat_mark_run ( ra8_fs_check_ctx_t * ctx,
uint32_t first,
uint64_t nclus )

Exercise the exFAT contiguous-run marker from a host unit test.

Marks a synthetic NoFatChain run directly so an exact full-volume run and a one-cluster overrun from cluster two can be distinguished. That geometry is impossible through a public exFAT file because the filesystem's system files also own data clusters. Production code must call ra8_fs_check().

Parameters
[in,out]ctxSynthetic scan context and caller-owned bitmap.
[in]firstFirst cluster of the contiguous run.
[in]nclusDeclared run length in clusters.
Returns
Nothing.
Precondition
ctx, its report and bitmap are non-NULL.
ctx->rep->clusters_total and nclus are non-zero.
Postcondition
The in-range prefix is marked.
An overrun records k_ra8_fs_check_fault_bad_dir_entry.
Note
Test-only and not thread-safe; no filesystem lock is acquired.
MC/DC:
Host vectors independently select an exact in-range run and a one-cluster overrun.
Since
0.1.0

Definition at line 168 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_mark_run().

◆ ra8_fs_check_test_exfat_push_overflow()

void ra8_fs_check_test_exfat_push_overflow ( ra8_fs_check_ctx_t * ctx,
uint32_t cluster,
bool already_truncated )

Exercise the exFAT directory-worklist overflow guard from a host test.

Builds an already-full private worklist and attempts one push. This drives the bounded-stack guard without constructing 129 simultaneous directories in a RAM volume. Production code must call ra8_fs_check(), never this test seam.

Parameters
[in,out]ctxSynthetic context whose report receives a fault.
[in]clusterCluster recorded for the dropped directory.
[in]already_truncatedWhether a prior overflow was already recorded.
Returns
Nothing.
Precondition
ctx is non-NULL.
ctx owns a non-NULL, writable report.
Postcondition
A first overflow records one scan-truncated fault.
A repeated overflow records no additional fault.
Note
Test-only and not thread-safe; no filesystem lock is acquired.
Since
0.1.0

Definition at line 449 of file ra8_fs_fat_exfat_check.c.

References internal_exchk_push(), and k_ra8_fs_check_max_dirs.