|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
FAT read / write / seek / tell / size I/O. 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.
Data Structures | |
| struct | write_walk_t |
| Forward waypoint carried across one write's grow-walks. More... | |
Functions | |
| static ra8_err_t | internal_skip_clusters (const ra8_fs_mount_t *m, uint32_t start, uint32_t n, uint32_t *out) |
| Walk n clusters forward from start along the FAT chain. | |
| static ra8_err_t | internal_read_one_chunk (ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take) |
| Read up to one sector's worth of bytes at the file's current offset. | |
| static ra8_err_t | internal_read_span (ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take) |
| Read one span, serving zeros past exFAT's ValidDataLength. | |
| static ra8_err_t | internal_read_locked (ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len) |
| Read bytes – the guarded body of ra8_fs_read(). | |
| ra8_err_t | priv_alloc_eoc_cluster (const ra8_fs_mount_t *m, uint32_t *out_c) |
| Allocate a fresh cluster, mark it EOC, and return its number. | |
| static ra8_err_t | internal_walk_grow (const ra8_fs_mount_t *m, uint32_t start, uint32_t idx, uint32_t *out_cluster) |
| Walk to cluster index idx from start, growing the chain as needed. | |
| ra8_err_t | priv_write_into_sector (const ra8_fs_mount_t *m, uint64_t lba, uint32_t off_in_sector, const uint8_t *src, uint32_t put) |
| Implementation of priv_write_into_sector() – one read-modify-write. | |
| static ra8_err_t | internal_write_position (ra8_fs_file_t *file, write_walk_t *way, uint32_t idx, uint32_t *out_cluster) |
Position the write cursor at chain index idx, growing as needed. | |
| static ra8_err_t | internal_write_stream (ra8_fs_file_t *file, const uint8_t *buf, uint32_t len) |
| Inner write loop: stream len bytes from buf into the file's chain. | |
| static ra8_err_t | internal_write_locked (ra8_fs_file_t *file, const uint8_t *buf, uint32_t len) |
| Write bytes – the guarded body of ra8_fs_write(). | |
| static ra8_err_t | internal_write_file_locked (ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len) |
| Create a whole file – the guarded body of ra8_fs_write_file(). | |
| static ra8_err_t | internal_seek_locked (ra8_fs_file_t *file, uint64_t offset_bytes) |
| Move the cursor – the guarded body of ra8_fs_seek(). | |
| static ra8_err_t | internal_tell_locked (const ra8_fs_file_t *file, uint64_t *out_offset) |
| Report the cursor – the guarded body of ra8_fs_tell(). | |
| static ra8_err_t | internal_size_locked (const ra8_fs_file_t *file, uint64_t *out_bytes) |
| Report the size – the guarded body of ra8_fs_size(). | |
| ra8_err_t | ra8_fs_read (ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len) |
| Read up to max_len bytes; advance the cluster chain on cluster crossings. | |
| ra8_err_t | ra8_fs_write (ra8_fs_file_t *file, const uint8_t *buf, uint32_t len) |
| Write len bytes; allocate new clusters from FAT free-space scan as needed. | |
| ra8_err_t | ra8_fs_write_file (ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len) |
| Create a whole file in one call (provisioning helper). | |
| ra8_err_t | ra8_fs_seek (ra8_fs_file_t *file, uint64_t offset_bytes) |
| Move the file offset to offset_bytes (clamped to size). | |
| ra8_err_t | ra8_fs_tell (const ra8_fs_file_t *file, uint64_t *out_offset) |
| Report the current offset (64-bit; see ra8_fs_seek). | |
| ra8_err_t | ra8_fs_size (const ra8_fs_file_t *file, uint64_t *out_bytes) |
| Report the file's size in bytes (64-bit on exFAT, #676). | |
FAT read / write / seek / tell / size I/O.
Cluster-chain skip/grow, sector-granular read and write streaming, and the public read/write/seek/tell/size entry points.
Definition in file ra8_fs_fat_fileio.c.
|
static |
Read bytes – the guarded body of ra8_fs_read().
Loops on priv_read_one_chunk, advancing file->offset after each chunk. Stops at EOF or when max_len met.
| [in,out] | file | Open file handle. |
| [out] | buf | Destination buffer. |
| [in] | max_len | Maximum bytes to read. |
| [out] | got_len | Bytes actually read. |
| k_ra8_ok | Read completed (possibly short at EOF). |
| k_ra8_err_null_ptr | Any pointer was NULL. |
| k_ra8_err_invalid_state | File is not open. |
| k_ra8_err_* | Backend error. |
Definition at line 245 of file ra8_fs_fat_fileio.c.
References internal_read_locked(), internal_read_span(), k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by internal_read_locked(), and ra8_fs_read().
|
static |
Read up to one sector's worth of bytes at the file's current offset.
Resolves the cluster covering file->offset, reads the containing sector, and copies the relevant slice into buf.
| [in,out] | file | File handle providing offset and chain root. |
| [out] | buf | Destination of the byte slice. |
| [in] | remaining | Maximum bytes the caller can accept. |
| [out] | out_take | Number of bytes actually copied. |
| k_ra8_ok | Slice copied. |
| k_ra8_err_* | Backend or FAT error. |
Definition at line 98 of file ra8_fs_fat_fileio.c.
References internal_skip_clusters(), k_cluster_first_data, k_ra8_ok, priv_bps(), priv_byte_copy(), priv_cluster_bytes(), priv_cluster_to_lba(), priv_read_sector(), and priv_sec_io().
Referenced by internal_read_span().
|
static |
Read one span, serving zeros past exFAT's ValidDataLength.
exFAT spec sec 7.4.5 splits a file in two: the prefix below ValidDataLength was written, and everything from there to DataLength was never initialised. Those bytes must read as zero, and the clusters behind them still hold whatever the previous tenant left, so serving them raw would hand a caller another file's data. A FAT handle has no such split – DIR_FileSize IS the written length – so it takes the same path with the two bounds equal and never reaches the hole arm.
| [in,out] | file | Open file handle. |
| [out] | buf | Destination of the span. |
| [in] | remaining | Maximum bytes the caller can accept. |
| [out] | out_take | Number of bytes actually produced. |
| k_ra8_ok | Span produced; *out_take > 0. |
| k_ra8_err_* | Backend or FAT error. |
Definition at line 195 of file ra8_fs_fat_fileio.c.
References internal_read_one_chunk(), k_ra8_fs_type_exfat, and k_ra8_ok.
Referenced by internal_read_locked().
|
static |
Move the cursor – the guarded body of ra8_fs_seek().
Clamps the requested offset to the current file size; the driver does not implement sparse files.
| [in,out] | file | Open file handle. |
| [in] | offset_bytes | Desired cursor position. |
| k_ra8_ok | Cursor moved (possibly clamped). |
| k_ra8_err_null_ptr | file was NULL. |
| k_ra8_err_invalid_state | File not open. |
Definition at line 662 of file ra8_fs_fat_fileio.c.
References internal_seek_locked(), k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by internal_seek_locked(), and ra8_fs_seek().
|
static |
Report the size – the guarded body of ra8_fs_size().
Reads file->size_bytes.
| [in] | file | Open file handle. |
| [out] | out_bytes | Receives the file size in bytes. |
| k_ra8_ok | Size returned. |
| k_ra8_err_null_ptr | Any pointer was NULL. |
| k_ra8_err_invalid_state | File not open. |
Definition at line 740 of file ra8_fs_fat_fileio.c.
References internal_size_locked(), k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by internal_size_locked(), and ra8_fs_size().
|
static |
Walk n clusters forward from start along the FAT chain.
Used by the read path to position to the cluster covering file->offset. Stops early on EOC.
| [in] | m | Mount providing FAT access. |
| [in] | start | First cluster of the chain. |
| [in] | n | Number of clusters to walk. |
| [out] | out | Receives the cluster reached (or last before EOC). |
| k_ra8_ok | Walked exactly n clusters. |
| k_ra8_err_invalid_state | Hit EOC before walking n clusters. |
| k_ra8_err_* | Backend error. |
Definition at line 53 of file ra8_fs_fat_fileio.c.
References k_ra8_err_invalid_state, k_ra8_ok, priv_fat_get(), and priv_is_eoc().
Referenced by internal_read_one_chunk().
|
static |
Report the cursor – the guarded body of ra8_fs_tell().
Reads file->offset.
| [in] | file | Open file handle. |
| [out] | out_offset | Receives the current offset in bytes. |
| k_ra8_ok | Position returned. |
| k_ra8_err_null_ptr | Any pointer was NULL. |
| k_ra8_err_invalid_state | File not open. |
Definition at line 703 of file ra8_fs_fat_fileio.c.
References internal_tell_locked(), k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by internal_tell_locked(), and ra8_fs_tell().
|
static |
Walk to cluster index idx from start, growing the chain as needed.
Like priv_skip_clusters but extends the chain (with new EOC clusters) when EOC is encountered before reaching idx.
| [in] | m | Mount providing FAT access. |
| [in] | start | First cluster of the chain. |
| [in] | idx | Index to walk to. |
| [out] | out_cluster | Receives the cluster at index idx. |
| k_ra8_ok | Reached / created cluster at idx. |
| k_ra8_err_* | Backend, FAT, or no-mem error. |
Definition at line 313 of file ra8_fs_fat_fileio.c.
References k_ra8_ok, priv_alloc_eoc_cluster(), priv_fat_get(), priv_fat_set(), and priv_is_eoc().
Referenced by internal_write_position().
|
static |
Create a whole file – the guarded body of ra8_fs_write_file().
Drives the unlocked open / write / close bodies – taking the library lock again here would deadlock a non-recursive mutex. The public ra8_fs_write_file() is the wrapper that holds the lock across all three, so the whole creation is one atomic operation rather than three.
There is no longer a second, exFAT-only path here: exFAT streams through the same three calls now that ra8_fs_open accepts a writing mode on it (#602), which is the point – two implementations of one verb are two places for it to mean different things.
| [in,out] | handle | Mounted volume. |
| [in] | path | Root-level file name, UTF-8. |
| [in] | data | File contents. |
| [in] | len | Byte count. |
| k_ra8_ok | File created and written. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_state | Mount is not in use. |
| k_ra8_err_* | As documented for ra8_fs_write_file(). |
path resolves to len bytes of data. Definition at line 607 of file ra8_fs_fat_fileio.c.
References internal_write_file_locked(), internal_write_locked(), k_ra8_err_null_ptr, k_ra8_fs_mode_write, k_ra8_ok, priv_close_locked(), and priv_open_locked().
Referenced by internal_write_file_locked(), and ra8_fs_write_file().
|
static |
Write bytes – the guarded body of ra8_fs_write().
Forwards to priv_write_stream, then patches the on-disk dir entry with the updated first-cluster and file size.
| [in,out] | file | File handle. |
| [in] | buf | Source buffer. |
| [in] | len | Bytes to write. |
| k_ra8_ok | All bytes written. |
| k_ra8_err_null_ptr | file or buf was NULL. |
| k_ra8_err_invalid_state | File not open or opened read-only. |
| k_ra8_err_* | Backend, FAT, or no-mem error. |
Definition at line 519 of file ra8_fs_fat_fileio.c.
References internal_write_locked(), k_ra8_err_null_ptr, k_ra8_fs_mode_read, k_ra8_fs_type_exfat, k_ra8_ok, and priv_exfat_flush_set().
Referenced by internal_write_file_locked(), internal_write_locked(), and ra8_fs_write().
|
static |
Position the write cursor at chain index idx, growing as needed.
Allocates the file's first cluster when it has none, then walks forward from the waypoint – not from the chain head – extending the chain if the walk runs off the end. The waypoint is advanced to wherever the walk landed.
| [in,out] | file | File handle whose chain is being extended. |
| [in,out] | way | Forward waypoint, advanced on success. |
| [in] | idx | Chain index the write needs. |
| [out] | out_cluster | Receives the cluster at idx. |
| k_ra8_ok | Cursor positioned; *out_cluster is valid. |
| k_ra8_err_no_mem | The volume has no free cluster to grow into. |
| k_ra8_err_* | Backend or FAT error. |
idx. Definition at line 404 of file ra8_fs_fat_fileio.c.
References write_walk_t::cluster, write_walk_t::index, internal_walk_grow(), k_cluster_first_data, k_ra8_ok, and priv_alloc_eoc_cluster().
Referenced by internal_write_stream().
|
static |
Inner write loop: stream len bytes from buf into the file's chain.
Allocates the first cluster on demand, then walks/grows the chain as needed and forwards each sector slice through priv_write_into_sector.
| [in,out] | file | File handle providing chain root and offset. |
| [in] | buf | Source buffer. |
| [in] | len | Number of bytes to write. |
| k_ra8_ok | All len bytes written. |
| k_ra8_err_* | Backend, FAT, or no-mem error. |
Definition at line 454 of file ra8_fs_fat_fileio.c.
References internal_write_position(), k_ra8_ok, priv_bps(), priv_cluster_bytes(), priv_cluster_to_lba(), and priv_write_into_sector().
| ra8_err_t priv_alloc_eoc_cluster | ( | const ra8_fs_mount_t * | m, |
| uint32_t * | out_c ) |
Allocate a fresh cluster, mark it EOC, and return its number.
Combines priv_alloc_cluster with a priv_fat_set to the canonical EOC value. Used by the write path when the file chain needs to grow.
| [in] | m | Mount providing FAT access. |
| [out] | out_c | Receives the allocated cluster. |
| k_ra8_ok | Cluster allocated and marked EOC. |
| k_ra8_err_* | Backend or FAT error. |
Definition at line 278 of file ra8_fs_fat_fileio.c.
References k_ra8_ok, priv_alloc_cluster(), priv_eoc_write(), and priv_fat_set().
Referenced by internal_dir_grow(), internal_fat_mkdir(), internal_fat_trunc_extend(), internal_walk_grow(), and internal_write_position().
| ra8_err_t priv_write_into_sector | ( | const ra8_fs_mount_t * | m, |
| uint64_t | lba, | ||
| uint32_t | off_in_sector, | ||
| const uint8_t * | src, | ||
| uint32_t | put ) |
Implementation of priv_write_into_sector() – one read-modify-write.
Merge put bytes into one sector at lba, at off_in_sector.
Definition at line 341 of file ra8_fs_fat_fileio.c.
References k_ra8_ok, priv_byte_copy(), priv_read_sector(), priv_sec_io(), and priv_write_sector().
Referenced by internal_exfat_close_gap(), internal_write_stream(), and priv_exfat_write_stream().
|
nodiscard |
Read up to max_len bytes; advance the cluster chain on cluster crossings.
| [in] | file | Open file (any mode). |
| [out] | buf | Destination buffer. |
| [in] | max_len | Maximum bytes to copy. |
| [out] | got_len | Actual bytes read (0 at EOF). |
| k_ra8_ok | Read completed (got_len may be 0 = EOF). |
| k_ra8_err_null_ptr | Any pointer arg is NULL. |
| k_ra8_err_invalid_state | file->in_use == 0. |
Definition at line 758 of file ra8_fs_fat_fileio.c.
References internal_read_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_read().
Referenced by demo_read_test_file(), demo_read_verify(), fileops_read_back(), fs_fmt_create_and_verify(), fs_fmt_rename_and_verify(), imp_read_cache(), internal_compare(), internal_demo_read_once(), internal_import_fs_read(), internal_native_read(), internal_pc_font_or_halt(), internal_pc_read_cache(), internal_ra8_io_roundtrip_read_verify(), internal_ra8_vfs_compress_load_blob(), internal_read(), internal_read_font(), internal_read_stamp(), internal_read_whole_file(), internal_source_read(), internal_swap_vfs_read_verify(), internal_verify_book(), ra8_fs_read(), ra8_io_roundtrip_read_verify(), sd_demo_read_payload(), sdhi_demo_read_and_verify(), sh_sd_book_read(), and sh_sd_comic_read().
|
nodiscard |
Move the file offset to offset_bytes (clamped to size).
64-bit so any position in a >4 GiB exFAT file is reachable (#676).
| k_ra8_ok | Seek committed. |
| k_ra8_err_null_ptr | file is NULL. |
Definition at line 786 of file ra8_fs_fat_fileio.c.
References internal_seek_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_seek().
Referenced by internal_native_seek(), internal_seek(), internal_source_read(), ra8_fs_seek(), sh_sd_book_read(), and sh_sd_comic_read().
|
nodiscard |
Report the file's size in bytes (64-bit on exFAT, #676).
Definition at line 804 of file ra8_fs_fat_fileio.c.
References internal_size_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_size().
Referenced by imp_read_cache(), internal_crc_stream(), internal_mkfontimg_verify(), internal_native_size(), internal_read_whole_file(), internal_size(), internal_stream_open(), internal_verify_book_reopen(), ra8_fs_size(), and sh_sd_book_open().
|
nodiscard |
Report the current offset (64-bit; see ra8_fs_seek).
Definition at line 795 of file ra8_fs_fat_fileio.c.
References internal_tell_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_tell().
Referenced by internal_native_tell(), internal_tell(), and ra8_fs_tell().
|
nodiscard |
Write len bytes; allocate new clusters from FAT free-space scan as needed.
New clusters come from a scan that starts at the mount's next-free hint rather than at cluster 2, reading the FAT through a one-sector cache, so appending stays linear in the bytes written instead of quadratic. The directory entry's modification time advances with every call, and again when the handle is closed.
| k_ra8_ok | Wrote all bytes; size + dir entry updated. |
| k_ra8_err_null_ptr | file or buf NULL. |
| k_ra8_err_invalid_state | file not opened for writing. |
| k_ra8_err_invalid_size | FAT volume and the write would push the file past 4 GiB - 1 (DIR_FileSize is 32-bit); exFAT files have no such cap (#676). |
| k_ra8_err_no_mem | Volume out of free clusters. |
Definition at line 767 of file ra8_fs_fat_fileio.c.
References internal_write_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_write().
Referenced by internal_native_write(), internal_ra8_io_roundtrip_write_subdir(), internal_ra8_vfs_compress_store_blob(), internal_stream(), internal_stream_book(), internal_swap_vfs_write(), internal_write(), ra8_fs_write(), ra8_io_roundtrip_subdir_file(), and sdhi_demo_write_payload().
|
nodiscard |
Create a whole file in one call (provisioning helper).
Convenience wrapper, and nothing more: on EVERY filesystem it opens path in write mode, writes data, and closes. It carried a second, exFAT-only implementation until exFAT learned to stream (#602) – a whole-file creator that needed one contiguous run and the entire payload in RAM at once. Both limits are gone with it, and the one remaining path means the two filesystems can no longer disagree about what this call does.
An existing path is REPLACED on both filesystems: write mode truncates it, so its old contents are discarded and its clusters returned to the volume's free space. Calling this twice with the same name leaves exactly one file, of the second call's contents, with no space lost to the first.
| [in] | handle | Mounted volume. |
| [in] | path | File path, UTF-8; nested paths resolve on both filesystems, provided every intermediate directory exists. |
| [in] | data | File contents. |
| [in] | len | Byte count; 0 leaves an empty file. |
| k_ra8_ok | File created and written. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_arg | Empty/oversized name, or path names an existing directory. |
| k_ra8_err_access_denied | path exists and its read-only attribute is set (it would be replaced – refused). |
| k_ra8_err_no_mem | Out of free clusters or directory slots. |
| k_ra8_err_* | Backend error. |
path. path resolves to exactly one entry of len bytes. path short, not stale. Definition at line 777 of file ra8_fs_fat_fileio.c.
References internal_write_file_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_write_file().
Referenced by demo_file_ops(), demo_write_test_file(), eoh_provision_or_halt(), etoc_provision_one(), fileops_step_write(), fs_fmt_create_and_verify(), internal_demo_run(), internal_dispatch_and_cache(), internal_open_or_provision(), internal_pc_font_or_halt(), internal_pc_persist_and_verify_or_halt(), internal_populate(), internal_write_stamp(), ra8_fs_write_file(), ra8_io_roundtrip_root_file(), rabook_compile_from_epub(), and sd_demo_write_payload().