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

Runtime volume-label read/set (ra8_fs_get_label() / ra8_fs_set_label()). More...

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

Go to the source code of this file.

Functions

static uint32_t internal_fat_boot_label_off (const ra8_fs_mount_t *m)
 Byte offset of BS_VolLab in this volume's boot sector.
static void internal_label_from_raw (const uint8_t *raw11, char *out, uint32_t out_len)
 Decode an 11-byte packed FAT label into a trimmed ASCII string.
static ra8_err_t internal_fat_find_vol_id (const ra8_fs_mount_t *m, uint64_t *out_lba, uint32_t *out_off, uint8_t *out_entry)
 Find the root directory's ATTR_VOLUME_ID entry.
static ra8_err_t internal_fat_find_free_root (const ra8_fs_mount_t *m, uint64_t *out_lba, uint32_t *out_off)
 Find the first free slot in the root directory.
static ra8_err_t internal_fat_boot_set_label (const ra8_fs_mount_t *m, const char *label)
 Write the boot sector's BS_VolLab field.
static ra8_err_t internal_fat_del_entry (const ra8_fs_mount_t *m, uint64_t lba, uint32_t off)
 Mark the root directory entry at lba / off deleted.
static ra8_err_t internal_fat_put_vol_id (const ra8_fs_mount_t *m, uint64_t lba, uint32_t off, const char *label, bool fresh)
 Write a root-directory ATTR_VOLUME_ID entry at lba / off.
static ra8_err_t internal_get_label_fat (const ra8_fs_mount_t *m, char *out, uint32_t out_len)
 Read a FAT volume's label – root ATTR_VOLUME_ID, else BS_VolLab.
static ra8_err_t internal_set_label_fat (const ra8_fs_mount_t *m, const char *label)
 Set a FAT volume's label – boot sector plus root entry, kept in step.
static ra8_err_t internal_get_label_locked (const ra8_fs_mount_t *handle, char *out, uint32_t out_len)
 Read the volume label – the guarded body of ra8_fs_get_label().
static ra8_err_t internal_set_label_locked (const ra8_fs_mount_t *handle, const char *label)
 Set the volume label – the guarded body of ra8_fs_set_label().
ra8_err_t ra8_fs_get_label (const ra8_fs_mount_t *handle, char *out, uint32_t out_len)
 Read the volume label of a mounted volume.
ra8_err_t ra8_fs_set_label (const ra8_fs_mount_t *handle, const char *label)
 Set (or clear) the volume label of a mounted volume.

Detailed Description

Runtime volume-label read/set (ra8_fs_get_label() / ra8_fs_set_label()).

The human name of the medium, readable and changeable after format. On FAT the label lives in two places kept in step: the boot sector's BS_VolLab field, and a root-directory ATTR_VOLUME_ID entry (the copy a desktop shows and edits). Setting a real label writes both – creating the root entry when absent – so fsck.fat never sees a blank or a mismatched label; clearing the label restores the "NO NAME " sentinel in the boot sector and removes the root entry. Reading prefers the root entry, falling back to BS_VolLab, and reports the unlabelled sentinel as the empty string.

The exFAT half of both operations lives in ra8_fs_fat_exfat_label.c; this file owns the FAT path and the public lock-bracketed entry points that dispatch to one or the other.

References (every shorthand citation in this file):

  • "MS FAT spec" = Microsoft Corp., "FAT: General Overview of On-Disk Format", v1.03, December 6 2000, section 3.1 (BS_VolLab) and section 6 (ATTR_VOLUME_ID).

NASA Power-of-Ten compliance:

  • Rule 2: the root-directory walks terminate on end-of-directory or the walker's own cluster-cycle guard; the copy loops are bounded by the 11-byte label field.
  • Rule 3: zero malloc; one 512-byte sector buffer on the stack.
  • Rule 7: every backend call is checked.
Since
0.1.0

Definition in file ra8_fs_fat_label.c.

Function Documentation

◆ internal_fat_boot_label_off()

uint32_t internal_fat_boot_label_off ( const ra8_fs_mount_t * m)
static

Byte offset of BS_VolLab in this volume's boot sector.

FAT32 carries its extended boot signature (and so its label) at a different offset than FAT12/16, because the FAT32 BPB is longer.

Parameters
[in]mMounted FAT volume.
Returns
The BS_VolLab byte offset.
Return values
k_fmt_off_f32_labelFAT32.
k_fmt_off_f16_labelFAT12 / FAT16.
Precondition
m is non-NULL with m->type computed.
m->type is FAT12/16/32 (the caller has excluded exFAT).
Postcondition
No state modified.
The result is purely a function of m->type.
Note
Pure function; trivially thread-safe.
Since
0.1.0

Definition at line 66 of file ra8_fs_fat_label.c.

References k_fmt_off_f16_label, k_fmt_off_f32_label, k_ra8_fs_type_fat32, and ra8_fs_mount_t::type.

Referenced by internal_fat_boot_set_label(), and internal_get_label_fat().

◆ internal_fat_boot_set_label()

ra8_err_t internal_fat_boot_set_label ( const ra8_fs_mount_t * m,
const char * label )
static

Write the boot sector's BS_VolLab field.

Read-modify-write of sector 0: the label field is replaced with the padded label (or the "NO NAME " sentinel when label is NULL / empty, via priv_fmt_label_field) and every other byte is preserved.

Parameters
[in]mMounted FAT volume.
[in]labelNew label, or NULL / "" for the unlabelled sentinel.
Returns
Error code.
Return values
k_ra8_okBoot sector updated.
k_ra8_err_*Backend read/write failure.
Precondition
m is non-NULL; m->type is FAT12/16/32.
The mount is in use.
Postcondition
On k_ra8_ok the boot sector's BS_VolLab reflects label.
No byte outside the label field changes.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 277 of file ra8_fs_fat_label.c.

References internal_fat_boot_label_off(), k_ra8_ok, priv_fmt_label_field(), priv_read_sector(), priv_sec_walk(), and priv_write_sector().

Referenced by internal_set_label_fat().

◆ internal_fat_del_entry()

ra8_err_t internal_fat_del_entry ( const ra8_fs_mount_t * m,
uint64_t lba,
uint32_t off )
static

Mark the root directory entry at lba / off deleted.

Writes the 0xE5 deleted marker to the entry's first name byte, preserving the rest of the sector.

Parameters
[in]mMounted FAT volume.
[in]lbaSector holding the entry.
[in]offByte offset of the entry within the sector.
Returns
Error code.
Return values
k_ra8_okEntry deleted.
k_ra8_err_*Backend read/write failure.
Precondition
m is non-NULL; lba / off came from ::priv_fat_find_vol_id.
The mount is in use.
Postcondition
On k_ra8_ok the entry no longer resolves.
No other directory byte changes.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 312 of file ra8_fs_fat_label.c.

References k_dir_marker_free_used, k_dir_off_name, k_ra8_ok, priv_read_sector(), priv_sec_walk(), and priv_write_sector().

Referenced by internal_set_label_fat().

◆ internal_fat_find_free_root()

ra8_err_t internal_fat_find_free_root ( const ra8_fs_mount_t * m,
uint64_t * out_lba,
uint32_t * out_off )
static

Find the first free slot in the root directory.

Walks the root for the first entry whose name field is 0x00 (never used, end-of-directory) or 0xE5 (deleted) – where a fresh volume-label entry can be written.

Parameters
[in]mMounted FAT volume.
[out]out_lbaSector holding the free slot.
[out]out_offByte offset of the slot within the sector.
Returns
Error code.
Return values
k_ra8_okFree slot found; outputs populated.
k_ra8_err_no_memThe root directory is full.
k_ra8_err_*Backend read failure.
Precondition
All pointers are non-NULL; m->type is FAT12/16/32.
The mount is in use.
Postcondition
On k_ra8_ok the outputs address a writable slot.
No volume state is modified.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 222 of file ra8_fs_fat_label.c.

References dir_walk_t::cur_lba, k_dir_marker_free_perm, k_dir_marker_free_used, k_dir_off_name, k_ra8_err_no_mem, k_ra8_fs_dir_entry_bytes, k_ra8_ok, priv_dir_eps(), priv_dir_walk_init_loc(), priv_dir_walk_next_sector(), priv_read_sector(), and priv_sec_walk().

Referenced by internal_set_label_fat().

◆ internal_fat_find_vol_id()

ra8_err_t internal_fat_find_vol_id ( const ra8_fs_mount_t * m,
uint64_t * out_lba,
uint32_t * out_off,
uint8_t * out_entry )
static

Find the root directory's ATTR_VOLUME_ID entry.

Walks the root directory (a FAT12/16 fixed region or a FAT32 root cluster chain) for the volume-label entry: an in-use entry whose attribute byte has the ATTR_VOLUME_ID bit but is not the 0x0F long-name marker. Stops at end-of-directory.

Parameters
[in]mMounted FAT volume.
[out]out_lbaSector holding the entry.
[out]out_offByte offset of the entry within the sector.
[out]out_entryThe 32-byte entry.
Returns
Error code.
Return values
k_ra8_okEntry found; outputs populated.
k_ra8_err_not_foundNo volume-label entry in the root directory.
k_ra8_err_*Backend read failure.
Precondition
All pointers are non-NULL; m->type is FAT12/16/32.
The mount is in use.
Postcondition
On k_ra8_ok the outputs address the entry on disk.
No volume state is modified.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 152 of file ra8_fs_fat_label.c.

References dir_walk_t::cur_lba, k_dir_marker_free_perm, k_dir_marker_free_used, k_dir_off_attr, k_dir_off_name, k_ra8_err_not_found, k_ra8_fs_attr_lfn, k_ra8_fs_attr_volume_id, k_ra8_fs_dir_entry_bytes, k_ra8_ok, priv_byte_copy(), priv_dir_eps(), priv_dir_walk_init_loc(), priv_dir_walk_next_sector(), priv_read_sector(), and priv_sec_walk().

Referenced by internal_get_label_fat(), and internal_set_label_fat().

◆ internal_fat_put_vol_id()

ra8_err_t internal_fat_put_vol_id ( const ra8_fs_mount_t * m,
uint64_t lba,
uint32_t off,
const char * label,
bool fresh )
static

Write a root-directory ATTR_VOLUME_ID entry at lba / off.

Read-modify-write of the sector: a fresh slot is zeroed first and stamped with a create time; an existing entry keeps its create fields and gets a write-time stamp. Either way the 11-byte name becomes the padded label and the attribute byte becomes ATTR_VOLUME_ID.

Parameters
[in]mMounted FAT volume.
[in]lbaSector holding the slot.
[in]offByte offset of the slot within the sector.
[in]labelLabel to store (non-empty).
[in]freshtrue to build a brand-new entry, false to rewrite one.
Returns
Error code.
Return values
k_ra8_okEntry written.
k_ra8_err_*Backend read/write failure.
Precondition
m and label are non-NULL; lba / off address a writable slot.
The mount is in use.
Postcondition
On k_ra8_ok the slot holds a stamped volume-label entry naming label.
No byte outside the entry changes.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 351 of file ra8_fs_fat_label.c.

References k_dir_off_attr, k_dir_off_name, k_ra8_fs_attr_volume_id, k_ra8_fs_dir_entry_bytes, k_ra8_ok, priv_fat_entry_stamp_create(), priv_fat_entry_stamp_write(), priv_fmt_label_field(), priv_read_sector(), priv_sec_walk(), and priv_write_sector().

Referenced by internal_set_label_fat().

◆ internal_get_label_fat()

ra8_err_t internal_get_label_fat ( const ra8_fs_mount_t * m,
char * out,
uint32_t out_len )
static

Read a FAT volume's label – root ATTR_VOLUME_ID, else BS_VolLab.

Prefers the root-directory volume-label entry (the copy a desktop shows); when the root carries none it falls back to the boot sector's BS_VolLab. The 11-byte field is decoded by ::priv_label_from_raw.

Parameters
[in]mMounted FAT volume.
[out]outBuffer receiving the NUL-terminated label.
[in]out_lenCapacity of out in bytes (at least 1).
Returns
Error code.
Return values
k_ra8_okout holds the label (possibly empty).
k_ra8_err_*Backend read failure.
Precondition
m and out are non-NULL; m->type is FAT12/16/32; out_len >= 1.
The mount is in use.
Postcondition
out is NUL-terminated.
No volume state is modified.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 403 of file ra8_fs_fat_label.c.

References internal_fat_boot_label_off(), internal_fat_find_vol_id(), internal_label_from_raw(), k_dir_off_name, k_fmt_label_len, k_ra8_err_not_found, k_ra8_fs_dir_entry_bytes, k_ra8_ok, priv_byte_copy(), priv_read_sector(), and priv_sec_walk().

Referenced by internal_get_label_locked().

◆ internal_get_label_locked()

ra8_err_t internal_get_label_locked ( const ra8_fs_mount_t * handle,
char * out,
uint32_t out_len )
static

Read the volume label – the guarded body of ra8_fs_get_label().

Validates the arguments, then dispatches to the FAT or exFAT reader. The public ra8_fs_get_label brackets this with the library lock; the full contract is documented there.

Parameters
[in]handleMount handle.
[out]outBuffer receiving the NUL-terminated label.
[in]out_lenCapacity of out in bytes.
Returns
Error code.
Return values
k_ra8_okLabel written.
k_ra8_err_null_ptrhandle or out is NULL.
k_ra8_err_invalid_argout_len is 0.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_*Backend read failure.
Precondition
The library lock is held (or none is installed).
handle and out are non-NULL.
Postcondition
On k_ra8_ok out is NUL-terminated.
No volume state is modified.
Note
Never call this from outside ra8_fs; it is the unlocked half.
The null-pointer guard's MC/DC vectors live in test_ra8_fs_label.c (test_label_get_null_guard).
Since
0.1.0

Definition at line 512 of file ra8_fs_fat_label.c.

References internal_get_label_fat(), internal_get_label_locked(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, and k_ra8_fs_type_exfat.

Referenced by internal_get_label_locked(), and ra8_fs_get_label().

◆ internal_label_from_raw()

void internal_label_from_raw ( const uint8_t * raw11,
char * out,
uint32_t out_len )
static

Decode an 11-byte packed FAT label into a trimmed ASCII string.

Copies the field, strips trailing padding (spaces or NULs), and reports the unlabelled sentinel "NO NAME " as the empty string – the same "no label" meaning FAT gives it. The result is NUL-terminated and truncated to out_len.

Parameters
[in]raw11The 11-byte BS_VolLab / ATTR_VOLUME_ID name field.
[out]outBuffer receiving the NUL-terminated label.
[in]out_lenCapacity of out in bytes (at least 1).
Returns
Nothing.
Precondition
raw11 and out are non-NULL; out_len >= 1.
raw11 addresses 11 readable bytes.
Postcondition
out is NUL-terminated (possibly truncated).
No byte past out[out_len-1] is written.
Note
Bounded loop (NASA Rule 2): at most k_fmt_label_len iterations.
Since
0.1.0

Definition at line 96 of file ra8_fs_fat_label.c.

References k_fmt_label_len, and priv_byte_equal().

Referenced by internal_get_label_fat().

◆ internal_set_label_fat()

ra8_err_t internal_set_label_fat ( const ra8_fs_mount_t * m,
const char * label )
static

Set a FAT volume's label – boot sector plus root entry, kept in step.

Writes BS_VolLab (the sentinel when clearing), then reconciles the root-directory volume-label entry: a real label rewrites the existing entry or creates one in a free slot; clearing deletes it. Keeping the two copies consistent is what keeps fsck.fat quiet.

Parameters
[in]mMounted FAT volume.
[in]labelNew label, or NULL / "" to clear it.
Returns
Error code.
Return values
k_ra8_okLabel written.
k_ra8_err_no_memThe root directory has no free slot for a new entry.
k_ra8_err_*Backend read/write failure.
Precondition
m is non-NULL; m->type is FAT12/16/32; the mount is in use.
The library lock is held, and label (when non-NULL) is <= 11 chars (the caller ::priv_set_label_locked has checked both).
Postcondition
On k_ra8_ok a later ::priv_get_label_fat reports label.
The boot-sector and root-directory labels agree.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 453 of file ra8_fs_fat_label.c.

References internal_fat_boot_set_label(), internal_fat_del_entry(), internal_fat_find_free_root(), internal_fat_find_vol_id(), internal_fat_put_vol_id(), k_ra8_err_not_found, k_ra8_fs_dir_entry_bytes, and k_ra8_ok.

Referenced by internal_set_label_locked().

◆ internal_set_label_locked()

ra8_err_t internal_set_label_locked ( const ra8_fs_mount_t * handle,
const char * label )
static

Set the volume label – the guarded body of ra8_fs_set_label().

Validates the arguments (rejecting a label longer than the 11-byte field), then dispatches to the FAT or exFAT writer. The public ra8_fs_set_label brackets this with the library lock; the full contract is documented there.

Parameters
[in]handleMount handle.
[in]labelNew label (<= 11 characters), or NULL / "" to clear it.
Returns
Error code.
Return values
k_ra8_okLabel written.
k_ra8_err_null_ptrhandle is NULL.
k_ra8_err_invalid_arglabel is longer than 11 characters.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_no_memNo free root slot for a new label entry.
k_ra8_err_*Backend read/write failure.
Precondition
The library lock is held (or none is installed).
handle is non-NULL.
Postcondition
On k_ra8_ok a later ra8_fs_get_label reports label.
On an argument error the volume is unchanged.
Note
Never call this from outside ra8_fs; it is the unlocked half.
The over-long-label guard's MC/DC vectors live in test_ra8_fs_label.c (test_label_set_guard).
Since
0.1.0

Definition at line 562 of file ra8_fs_fat_label.c.

References internal_set_label_fat(), internal_set_label_locked(), k_fmt_label_len, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_fs_type_exfat, and priv_strlen().

Referenced by internal_set_label_locked(), and ra8_fs_set_label().

◆ ra8_fs_get_label()

ra8_err_t ra8_fs_get_label ( const ra8_fs_mount_t * handle,
char * out,
uint32_t out_len )
nodiscard

Read the volume label of a mounted volume.

On FAT the label is read from the root directory's ATTR_VOLUME_ID entry when one exists (the copy a desktop shows and edits), falling back to the boot sector's BS_VolLab; the specification's unlabelled sentinel "NO NAME " reports as the empty string. On exFAT the root-directory Volume Label entry (type 0x83) is decoded from UTF-16LE. The result is NUL-terminated and stripped of trailing padding spaces.

Parameters
[in]handleMount handle.
[out]outBuffer receiving the NUL-terminated label.
[in]out_lenCapacity of out in bytes; k_ra8_fs_label_cap holds any label this filesystem can store.
Returns
ra8_err_t Error code.
Return values
k_ra8_okLabel written to out (possibly empty).
k_ra8_err_null_ptrhandle or out is NULL.
k_ra8_err_invalid_argout_len is 0.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_*Backend read failure.
Precondition
handle and out are non-NULL; out_len >= 1.
Mount is in use.
Postcondition
On k_ra8_ok out is NUL-terminated (truncated to fit out_len).
No volume state is modified.
Note
Not thread-safe unless a lock is installed (see ra8_fs_set_lock()).
See also
ra8_fs_set_label()
Since
0.1.0

Definition at line 585 of file ra8_fs_fat_label.c.

References internal_get_label_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_get_label().

Referenced by ra8_fs_get_label().

◆ ra8_fs_set_label()

ra8_err_t ra8_fs_set_label ( const ra8_fs_mount_t * handle,
const char * label )
nodiscard

Set (or clear) the volume label of a mounted volume.

On FAT the boot sector's BS_VolLab and the root directory's ATTR_VOLUME_ID entry are kept in step: a non-empty label writes both (creating the root entry if absent), an empty label restores the "NO NAME " sentinel and removes the root entry, so fsck.fat reports neither a blank nor a mismatched label. On exFAT the root Volume Label entry (type 0x83) is rewritten in place with the new UTF-16LE label and character count. Data and every other entry are untouched.

Parameters
[in]handleMount handle.
[in]labelNew label (<= 11 characters), or NULL / "" to clear it.
Returns
ra8_err_t Error code.
Return values
k_ra8_okLabel written.
k_ra8_err_null_ptrhandle is NULL.
k_ra8_err_invalid_arglabel is longer than 11 characters.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_no_memThe root directory has no free slot for a new label entry.
k_ra8_err_*Backend read/write failure.
Precondition
handle is non-NULL and the mount is in use.
No host label longer than 11 characters is requested.
Postcondition
On k_ra8_ok a later ra8_fs_get_label reports label (empty when label was NULL/"").
On an argument error the volume is unchanged.
Note
Not thread-safe unless a lock is installed (see ra8_fs_set_lock()).
See also
ra8_fs_get_label()
Since
0.1.0

Definition at line 594 of file ra8_fs_fat_label.c.

References internal_set_label_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_set_label().

Referenced by ra8_fs_set_label().