libdragon
Data Structures | Functions
eepromfs.h File Reference

EEPROM Filesystem. More...

Go to the source code of this file.

Data Structures

struct  eepfs_entry_t
 EEPROM filesystem configuration file entry. More...
 

Macros

EEPROM filesystem return values
#define EEPFS_ESUCCESS   0
 Success.
 
#define EEPFS_EBADINPUT   -1
 Input parameters invalid.
 
#define EEPFS_ENOFILE   -2
 File does not exist.
 
#define EEPFS_EBADFS   -3
 Bad filesystem.
 
#define EEPFS_ENOMEM   -4
 No memory for operation.
 
#define EEPFS_EBADHANDLE   -5
 Invalid file handle.
 
#define EEPFS_ECONFLICT   -6
 Filesystem already initialized.
 

Functions

int eepfs_init (const eepfs_entry_t *entries, size_t count)
 Initializes the EEPROM filesystem. More...
 
int eepfs_close (void)
 De-initializes the EEPROM filesystem. More...
 
int eepfs_read (const char *path, void *dest, size_t size)
 Reads an entire file from the EEPROM filesystem. More...
 
int eepfs_write (const char *path, const void *src, size_t size)
 Writes an entire file to the EEPROM filesystem. More...
 
int eepfs_erase (const char *path)
 Erases a file in the EEPROM filesystem. More...
 
bool eepfs_verify_signature (void)
 Validates the first block of EEPROM. More...
 
void eepfs_wipe (void)
 Erases all blocks in EEPROM and sets a new signature. More...
 

Detailed Description

EEPROM Filesystem.


Data Structure Documentation

◆ eepfs_entry_t

struct eepfs_entry_t

EEPROM filesystem configuration file entry.

See also
eepfs_init
Data Fields
const char * path File path.

This cannot be NULL and must be a \0-terminated string.

There are no enforced limitations on directory structure or file naming conventions except that all paths within the filesystem must be unique and at least one character.

A leading '/' is optional and will be ignored if set.

The filesytem does not support entries for directories, nor does it support listing files in a given directory.

size_t size File size in bytes.

In order to make the most use of limited EEPROM space, files should be (but are not required to be) aligned to the 8-byte block size. Unaligned bytes at the end of a file will be wasted as padding; files must start on a block boundary.

The filesystem itself reserves the first block of EEPROM, so your total filesystem size cannot exceed the available EEPROM size minus 8 bytes (64 bits):

  • 4k EEPROM: 512 - 8 = 504 bytes (63 blocks) free.
  • 16k EEPROM: 2048 - 8 = 2040 bytes (255 blocks) free.

Function Documentation

◆ eepfs_init()

int eepfs_init ( const eepfs_entry_t entries,
size_t  count 
)

Initializes the EEPROM filesystem.

Creates a lookup table of file descriptors based on the configuration and validates that the current EEPROM data is likely to be compatible with the configured file descriptors.

If the configured filesystem does not fit in the available EEPROM blocks on the cartridge, initialization will fail. Even if your total file size fits in EEPROM, your filesystem may not fit due to overhead and padding. Note that 1 block is reserved for the filesystem signature, and all files must start on a block boundary.

You can mitigate this by ensuring that your files are aligned to the 8-byte block size and minimizing wasted space with packed structs.

Each file will take up a minimum of 1 block, plus the filesystem itself reserves the first block of EEPROM, so the entry count has a practical limit of the number of available EEPROM blocks minus 1:

  • 4k EEPROM: 63 files maximum.
  • 16k EEPROM: 255 files maximum.
Parameters
[in]entriesAn array of file paths and sizes; see eepfs_entry_t
[in]countThe number of entries in the array
Returns
EEPFS_ESUCCESS on success or a negative error otherwise

◆ eepfs_close()

int eepfs_close ( void  )

De-initializes the EEPROM filesystem.

This cleans up the file lookup table.

You probably won't ever need to call this.

Returns
EEPFS_ESUCCESS on success or a negative error otherwise

◆ eepfs_read()

int eepfs_read ( const char *  path,
void *  dest,
size_t  size 
)

Reads an entire file from the EEPROM filesystem.

Parameters
[in]pathPath of file in EEPROM filesystem to read from
[out]destBuffer to read into
[in]sizeSize of the destination buffer (in bytes)
Returns
EEPFS_ESUCCESS on success or a negative error otherwise

◆ eepfs_write()

int eepfs_write ( const char *  path,
const void *  src,
size_t  size 
)

Writes an entire file to the EEPROM filesystem.

Each EEPROM block write takes approximately 15 milliseconds; this operation may block for a while!

Parameters
[in]pathPath of file in EEPROM filesystem to write to
[in]srcBuffer of data to be written
[in]sizeSize of the source buffer (in bytes)
Returns
EEPFS_ESUCCESS on success or a negative error otherwise

◆ eepfs_erase()

int eepfs_erase ( const char *  path)

Erases a file in the EEPROM filesystem.

Note that "erasing" a file just means writing it full of zeroes. All files in the filesystem must always exist at the size specified during eepfs_init

Each EEPROM block write takes approximately 15 milliseconds; this operation may block for a while!

Be advised: this is a destructive operation that cannot be undone!

Return values
EEPFS_ESUCCESSif successful
EEPFS_ENOFILEif the path is not a valid file
EEPFS_EBADINPUTif the path is NULL

◆ eepfs_verify_signature()

bool eepfs_verify_signature ( void  )

Validates the first block of EEPROM.

There are no guarantees that the data in EEPROM actually matches the expected layout of the filesystem. There are many reasons why a mismatch can occur: EEPROM re-used from another game; a brand new EEPROM that has never been initialized and contains garbage data; the filesystem has changed between builds or version of software currently in development; EEPROM failing due to age or write limits.

To mitigate these scenarios, it is a good idea to validate that at least the first block of EEPROM matches some known good value.

If the signature matches, the data in EEPROM is probably what the filesystem expects. If not, the best move is to erase everything and start from zero.

See also
eepfs_generate_signature
eepfs_wipe
Return values
trueif the signature in EEPROM matches the filesystem signature
falseif the signature in EEPROM does not match the filesystem signature

◆ eepfs_wipe()

void eepfs_wipe ( void  )

Erases all blocks in EEPROM and sets a new signature.

This is useful when you want to erase all files in the filesystem.

Each EEPROM block write takes approximately 15 milliseconds; this operation may block for a while:

  • 4k EEPROM: 64 blocks * 15ms = 960ms!
  • 16k EEPROM: 256 blocks * 15ms = 3840ms!

You may want to pause audio in advance of calling this.

Be advised: this is a destructive operation that cannot be undone!

See also
eepfs_verify_signature