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

Build an atomic deterministic exFAT showcase image through ra8_fs. More...

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "ra8_attributes.h"
#include "ra8_err.h"
#include "ra8_fs.h"
Include dependency graph for exfat_mkimage.c:

Go to the source code of this file.

Data Structures

struct  mk_disk_t
 Descriptor-backed card state bound into ra8_fs. More...
struct  mk_output_t
 Caller-owned atomic-publication state. More...
struct  mk_entry_t
 One showcase volume entry. More...

Macros

#define O_CLOEXEC   (0)
 No-op close-on-exec fallback for hosts lacking the flag.
#define O_DIRECTORY   (0)
 No-op directory-open fallback for hosts lacking the flag.
#define O_NOFOLLOW   (0)
 No-op no-follow fallback for hosts lacking the flag.

Enumerations

enum  mk_limit_t : uint32_t {
  k_mk_block_size = 512U ,
  k_mk_block_count = 131072U ,
  k_mk_payload = 32U ,
  k_mk_alphabet = 26U ,
  k_mk_path_cap = 4096U ,
  k_mk_name_cap = 256U ,
  k_mk_temp_attempts = 128U ,
  k_mk_decimal_digits = 20U ,
  k_mk_decimal_base = 10U ,
  k_mk_create_mode = 0666U
}
 Image geometry and bounded hosted-storage constants. More...

Functions

static void internal_log (int fd, const char *text)
 Write one complete diagnostic fragment to a raw descriptor.
static void internal_log_u64 (int fd, uint64_t value)
 Log one unsigned decimal value without a formatting stream.
static bool internal_pread_exact (int fd, uint64_t offset, uint8_t *bytes, size_t length)
 Read an exact positioned range from a regular descriptor.
static bool internal_pwrite_exact (int fd, uint64_t offset, const uint8_t *bytes, size_t length)
 Write an exact positioned range to a regular descriptor.
static bool internal_block_range (const mk_disk_t *disk, uint64_t lba, uint32_t count, uint64_t *out_offset, size_t *out_bytes)
 Translate one sector range into bounded hosted byte coordinates.
static ra8_err_t internal_disk_read (void *ctx, uint64_t lba, uint32_t count, uint8_t *buffer)
 Read blocks from the sparse unpublished image.
static ra8_err_t internal_disk_write (void *ctx, uint64_t lba, uint32_t count, const uint8_t *buffer)
 Write blocks into the sparse unpublished image.
static ra8_err_t internal_disk_capacity (void *ctx, uint64_t *block_count, uint32_t *block_size)
 Report the fixed card-image geometry.
static bool internal_split_output (const char *path, char parent[k_mk_path_cap], char leaf[k_mk_name_cap])
 Split a destination into bounded parent and leaf components.
static bool internal_temp_name (char out[k_mk_name_cap], uint64_t process, uint32_t attempt)
 Build one hidden temporary leaf from process id and retry index.
static bool internal_output_begin (const char *path, mk_output_t *output)
 Create and exact-size one private sibling temporary.
static void internal_output_abort (mk_output_t *output)
 Close and remove an unpublished temporary.
static bool internal_output_commit (mk_output_t *output)
 Sync and atomically publish one complete sibling temporary.
static ra8_err_t internal_populate (ra8_fs_mount_t *mount)
 Populate every deterministic UTF-8 showcase entry.
int main (int argc, char **argv)
 Format, populate, verify closure, and atomically publish one image.

Variables

static const mk_entry_t s_entries []
 Deterministic UTF-8 showcase contents.

Detailed Description

Build an atomic deterministic exFAT showcase image through ra8_fs.

Tag
[Ring 7 / TOOL] {World: NS}

Formats and populates a sparse sibling-temporary block device through the same callback-driven ra8_fs code used by firmware. The 64 MiB card is never resident: exact positioned descriptor I/O backs the block callbacks, and a complete synced temporary is atomically renamed over the destination only after the filesystem unmounts cleanly. The UTF-8 showcase content and final bytes remain identical to the legacy RAM-backed generator.

Since
0.1.0

Definition in file exfat_mkimage.c.

Macro Definition Documentation

◆ O_CLOEXEC

#define O_CLOEXEC   (0)

No-op close-on-exec fallback for hosts lacking the flag.

Definition at line 38 of file exfat_mkimage.c.

◆ O_DIRECTORY

◆ O_NOFOLLOW

#define O_NOFOLLOW   (0)

No-op no-follow fallback for hosts lacking the flag.

Definition at line 48 of file exfat_mkimage.c.

Enumeration Type Documentation

◆ mk_limit_t

enum mk_limit_t : uint32_t

Image geometry and bounded hosted-storage constants.

Enumerator
k_mk_block_size 

Bytes per image block.

k_mk_block_count 

Blocks in the 64 MiB image.

k_mk_payload 

Bytes in each showcase file.

k_mk_alphabet 

ASCII payload cycle length.

k_mk_path_cap 

Hosted path capacity.

k_mk_name_cap 

Hosted leaf capacity.

k_mk_temp_attempts 

Exclusive-create retry bound.

k_mk_decimal_digits 

Maximum uint64_t digits.

k_mk_decimal_base 

Decimal conversion radix.

k_mk_create_mode 

Hosted output creation mode.

Definition at line 52 of file exfat_mkimage.c.

Function Documentation

◆ internal_block_range()

bool internal_block_range ( const mk_disk_t * disk,
uint64_t lba,
uint32_t count,
uint64_t * out_offset,
size_t * out_bytes )
static

Translate one sector range into bounded hosted byte coordinates.

Checks geometry and every multiplication and host conversion first.

Parameters
[in]diskBound geometry.
[in]lbaFirst block.
[in]countBlock count.
[out]out_offsetByte offset.
[out]out_bytesByte count.
Returns
true only when the complete range is representable.
Return values
trueBoth outputs are populated.
falseGeometry or host integer bounds reject the range.
Precondition
All pointers are non-NULL and geometry is non-zero.
Count is the callback's requested extent.
Postcondition
Outputs change only on true.
Disk state remains unchanged.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 258 of file exfat_mkimage.c.

References mk_disk_t::block_count, mk_disk_t::block_size, and RA8_INTERNAL.

Referenced by internal_disk_read(), internal_disk_read(), internal_disk_read(), internal_disk_write(), internal_disk_write(), and internal_disk_write().

◆ internal_disk_capacity()

ra8_err_t internal_disk_capacity ( void * ctx,
uint64_t * block_count,
uint32_t * block_size )
static

Report the fixed card-image geometry.

Copies immutable block count and size fields into caller outputs.

Parameters
[in]ctxBound mk_disk_t context.
[out]block_countReceives the number of blocks.
[out]block_sizeReceives bytes per block.
Returns
Canonical block-device status.
Return values
k_ra8_okBoth outputs were initialized.
k_ra8_err_null_ptrA required pointer was null.
Precondition
All three pointers are non-null.
Context geometry was initialized before backend binding.
Postcondition
Success populates both outputs.
Context and descriptor state are unchanged.
Note
Read-only and thread-safe while the context remains alive.
Since
0.1.0

Definition at line 367 of file exfat_mkimage.c.

References mk_disk_t::block_count, mk_disk_t::block_size, k_ra8_err_null_ptr, and k_ra8_ok.

Referenced by main(), and priv_mkfontimg_host_begin().

◆ internal_disk_read()

ra8_err_t internal_disk_read ( void * ctx,
uint64_t lba,
uint32_t count,
uint8_t * buffer )
static

Read blocks from the sparse unpublished image.

Validates the complete range, performs exact positioned I/O, and records the first host failure in the transaction context.

Parameters
[in,out]ctxBound mk_disk_t context.
[in]lbaFirst block to read.
[in]countNumber of blocks to read.
[out]bufferDestination spanning count * block_size bytes.
Returns
Canonical block-device status.
Return values
k_ra8_okEvery requested block was read.
k_ra8_err_out_of_rangeState, pointer, or geometry was invalid.
k_ra8_failExact host I/O failed.
Precondition
ctx and buffer are non-null.
The bound descriptor remains open.
Postcondition
Success initializes the complete destination range.
Host failure leaves the disk error flag set.
Note
Not thread-safe through the shared sticky-error flag.
Since
0.1.0

Definition at line 298 of file exfat_mkimage.c.

References mk_disk_t::fd, internal_block_range(), internal_pread_exact(), mk_disk_t::io_failed, k_ra8_err_out_of_range, k_ra8_fail, and k_ra8_ok.

Referenced by main(), and priv_mkfontimg_host_begin().

◆ internal_disk_write()

ra8_err_t internal_disk_write ( void * ctx,
uint64_t lba,
uint32_t count,
const uint8_t * buffer )
static

Write blocks into the sparse unpublished image.

Validates the complete range, performs exact positioned I/O, and records the first host failure in the transaction context.

Parameters
[in,out]ctxBound mk_disk_t context.
[in]lbaFirst block to write.
[in]countNumber of blocks to write.
[in]bufferSource spanning count * block_size bytes.
Returns
Canonical block-device status.
Return values
k_ra8_okEvery requested block was written.
k_ra8_err_out_of_rangeState, pointer, or geometry was invalid.
k_ra8_failExact host I/O failed.
Precondition
ctx and buffer are non-null.
The bound descriptor remains open.
Postcondition
Success updates only the requested byte range.
Host failure leaves the disk error flag set.
Note
Not thread-safe for overlapping writes or shared error state.
Since
0.1.0

Definition at line 334 of file exfat_mkimage.c.

References mk_disk_t::fd, internal_block_range(), internal_pwrite_exact(), mk_disk_t::io_failed, k_ra8_err_out_of_range, k_ra8_fail, and k_ra8_ok.

Referenced by main(), and priv_mkfontimg_host_begin().

◆ internal_log()

void internal_log ( int fd,
const char * text )
static

Write one complete diagnostic fragment to a raw descriptor.

Retries interrupted and short writes without using stdio streams.

Parameters
[in]fdStandard output or standard error descriptor.
[in]textNUL-terminated fragment.
Precondition
text is non-NULL and NUL-terminated.
fd may accept or reject the write.
Postcondition
The complete fragment was attempted with short/EINTR handling.
No tool state changed.
Note
Fragments may interleave with another process.
Since
0.1.0

Definition at line 114 of file exfat_mkimage.c.

References RA8_INTERNAL, and strlen().

Referenced by internal_log_u64(), internal_populate(), and main().

◆ internal_log_u64()

void internal_log_u64 ( int fd,
uint64_t value )
static

Log one unsigned decimal value without a formatting stream.

Converts through fixed local arrays before one bounded log operation.

Parameters
[in]fdStandard output or standard error descriptor.
[in]valueValue to render.
Precondition
Fixed digit capacity covers every uint64 value.
fd may accept or reject the write.
Postcondition
Decimal spelling was attempted.
No tool state changed.
Note
Fragments may interleave with another process.
Since
0.1.0

Definition at line 142 of file exfat_mkimage.c.

References internal_log(), k_mk_decimal_base, k_mk_decimal_digits, and RA8_INTERNAL.

Referenced by internal_populate(), and main().

◆ internal_output_abort()

void internal_output_abort ( mk_output_t * output)
static

Close and remove an unpublished temporary.

Idempotently releases the image, private leaf, and parent descriptor.

Parameters
[in,out]outputPartially initialized output state.
Precondition
output is non-NULL and no mount uses its descriptor.
State came from internal_output_begin.
Postcondition
Every owned descriptor is closed.
Any owned temporary leaf is removed.
Note
Not thread-safe through output.
Since
0.1.0

Definition at line 537 of file exfat_mkimage.c.

References mk_output_t::directory_fd, mk_output_t::image_fd, RA8_INTERNAL, mk_output_t::temp_exists, and mk_output_t::temp_name.

Referenced by main().

◆ internal_output_begin()

bool internal_output_begin ( const char * path,
mk_output_t * output )
static

Create and exact-size one private sibling temporary.

Uses exclusive no-follow creation and unwinds partial acquisition.

Parameters
[in]pathRequested final path.
[out]outputReceives publication state.
Returns
true when the sparse temporary is open.
Return values
trueCaller owns the temporary and descriptors.
falseValidation or hosted setup failed without leakage.
Precondition
Both arguments are non-NULL and path is NUL-terminated.
Fixed image geometry is representable by off_t.
Postcondition
On true image length is exactly 64 MiB.
On false an existing destination is unchanged.
Note
Not thread-safe for the same destination path.
Since
0.1.0

Definition at line 484 of file exfat_mkimage.c.

References mk_output_t::directory_fd, mk_output_t::final_name, mk_output_t::image_fd, internal_split_output(), internal_temp_name(), k_mk_block_count, k_mk_block_size, k_mk_create_mode, k_mk_path_cap, k_mk_temp_attempts, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, RA8_INTERNAL, mk_output_t::temp_exists, and mk_output_t::temp_name.

Referenced by main().

◆ internal_output_commit()

bool internal_output_commit ( mk_output_t * output)
static

Sync and atomically publish one complete sibling temporary.

Syncs file data before rename and parent metadata after publication.

Parameters
[in,out]outputComplete output state no longer used by a mount.
Returns
true when file sync, close, rename, and directory sync succeed.
Return values
trueFinal leaf names the complete image.
falsePublication failed or durability is unconfirmed.
Precondition
output owns a complete unmounted image.
No further block callback will use its descriptor.
Postcondition
All descriptors are closed.
Successful rename leaves no temporary leaf.
Note
Directory-sync failure can follow a complete visible rename.
Since
0.1.0

Definition at line 567 of file exfat_mkimage.c.

References mk_output_t::directory_fd, mk_output_t::final_name, mk_output_t::image_fd, RA8_INTERNAL, renameat(), mk_output_t::temp_exists, and mk_output_t::temp_name.

Referenced by main().

◆ internal_populate()

ra8_err_t internal_populate ( ra8_fs_mount_t * mount)
static

Populate every deterministic UTF-8 showcase entry.

Creates entries in table order with one fixed bounded payload.

Parameters
[in,out]mountMounted exFAT volume.
Returns
ra8_fs status.
Return values
k_ra8_okEvery entry was created.
otherFirst filesystem failure.
Precondition
mount is live and writable.
Entry table ordering remains deterministic.
Postcondition
On success the complete showcase exists.
Each file holds the same fixed payload.
Note
Not thread-safe through ra8_fs global slots.
Since
0.1.0

Definition at line 609 of file exfat_mkimage.c.

References internal_log(), internal_log_u64(), mk_entry_t::is_dir, k_mk_alphabet, k_mk_payload, k_ra8_ok, mk_entry_t::meaning, mk_entry_t::path, ra8_fs_mkdir(), ra8_fs_write_file(), RA8_INTERNAL, and s_entries.

Referenced by main().

◆ internal_pread_exact()

bool internal_pread_exact ( int fd,
uint64_t offset,
uint8_t * bytes,
size_t length )
static

Read an exact positioned range from a regular descriptor.

Retries interruptions and rejects EOF before the requested length.

Parameters
[in]fdOpen image descriptor.
[in]offsetAbsolute byte offset.
[out]bytesExact-size destination.
[in]lengthRequired bytes.
Returns
true only when every byte was read.
Return values
trueDestination is complete.
falseOverflow, EOF, or hosted I/O failure occurred.
Precondition
bytes spans length writable bytes.
fd remains open.
Postcondition
Descriptor position is unchanged.
On false destination may hold a strict prefix.
Note
Thread-safe for independent buffers.
Since
0.1.0

Definition at line 176 of file exfat_mkimage.c.

Referenced by internal_disk_read().

◆ internal_pwrite_exact()

bool internal_pwrite_exact ( int fd,
uint64_t offset,
const uint8_t * bytes,
size_t length )
static

Write an exact positioned range to a regular descriptor.

Retries interruptions and treats a zero write as terminal failure.

Parameters
[in]fdOpen image descriptor.
[in]offsetAbsolute byte offset.
[in]bytesExact-size source.
[in]lengthRequired bytes.
Returns
true only when every byte was written.
Return values
trueComplete range reached the page cache.
falseOverflow or hosted I/O failure occurred.
Precondition
bytes spans length readable bytes.
fd remains open.
Postcondition
Descriptor position is unchanged.
On false only the unpublished temporary may be partial.
Note
Not thread-safe for overlapping ranges.
Since
0.1.0

Definition at line 217 of file exfat_mkimage.c.

Referenced by internal_disk_write(), and priv_rv_trace_reference().

◆ internal_split_output()

bool internal_split_output ( const char * path,
char parent[k_mk_path_cap],
char leaf[k_mk_name_cap] )
static

Split a destination into bounded parent and leaf components.

Rejects truncation, empty leaves, and dot traversal components.

Parameters
[in]pathRequested output.
[out]parentParent path.
[out]leafDestination leaf.
Returns
true only for a bounded usable leaf.
Return values
trueOutputs are populated.
falsePath is empty, long, or names ./../a directory.
Precondition
All arguments are non-NULL and outputs have fixed capacities.
path is NUL-terminated.
Postcondition
No filesystem object is touched.
On true parent and leaf reconstruct path.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 395 of file exfat_mkimage.c.

References k_mk_name_cap, k_mk_path_cap, memcpy(), strcmp(), and strlen().

Referenced by internal_output_begin().

◆ internal_temp_name()

bool internal_temp_name ( char out[k_mk_name_cap],
uint64_t process,
uint32_t attempt )
static

Build one hidden temporary leaf from process id and retry index.

Uses fixed decimal buffers so collision handling allocates nothing.

Parameters
[out]outTemporary leaf.
[in]processProcess identifier.
[in]attemptCollision retry index.
Returns
true only when the complete name fits.
Return values
trueout is NUL-terminated and slash-free.
falseFixed capacity is insufficient.
Precondition
Output has k_mk_name_cap bytes.
Numeric inputs are finite.
Postcondition
No filesystem object is touched.
Output depends only on arguments.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 445 of file exfat_mkimage.c.

References k_mk_decimal_base, k_mk_decimal_digits, k_mk_name_cap, memcpy(), and s_prefix.

Referenced by internal_output_begin().

◆ main()

int main ( int argc,
char ** argv )

Format, populate, verify closure, and atomically publish one image.

Parameters
[in]argcArgument count with at most one optional output path.
[in]argvArgument vector.
Returns
Process status.
Return values
0Complete deterministic exFAT image was published.
1Hosted storage or filesystem operation failed.
2Too many command-line arguments were supplied.
Precondition
Hosted runtime supplies argc valid strings in argv.
Destination parent directory exists.
Postcondition
On zero output has exact fixed image length.
Before rename, failure preserves an existing destination.
Note
Not thread-safe through ra8_fs global slots.
Since
0.1.0

Definition at line 652 of file exfat_mkimage.c.

References mk_output_t::image_fd, internal_disk_capacity(), internal_disk_read(), internal_disk_write(), internal_log(), internal_log_u64(), internal_output_abort(), internal_output_begin(), internal_output_commit(), internal_populate(), mk_disk_t::io_failed, k_mk_block_count, k_mk_block_size, k_ra8_fail, k_ra8_fs_type_exfat, k_ra8_ok, ra8_fs_format(), ra8_fs_mount(), and ra8_fs_unmount().

Variable Documentation

◆ s_entries

const mk_entry_t s_entries[]
static
Initial value:
= {
{"/\xD0\x9F\xD0\xB0\xD0\xBF\xD0\xBA\xD0\xB0", "Cyrillic directory (Papka)", true},
{"/\xE4\xBD\xA0\xE5\xA5\xBD", "CJK directory (ni hao)", true},
{"/Caf\xC3\xA9.txt", "Latin-1 accent (Cafe.txt)", false},
{"/\xE4\xBD\xA0\xE5\xA5\xBD.txt", "CJK filename", false},
{"/\xF0\x9F\x98\x80.txt", "astral-plane emoji, a surrogate pair on disk", false},
{"/\xD0\x9F\xD0\xB0\xD0\xBF\xD0\xBA\xD0\xB0/n\xC3\xB6te.txt",
"non-ASCII file inside a non-ASCII directory",
false},
{"/README.txt", "plain ASCII control", false},
}

Deterministic UTF-8 showcase contents.

Definition at line 90 of file exfat_mkimage.c.

Referenced by internal_populate().