libdragon
Data Structures | Files | Defines | Typedefs | Enumerations | Functions | Variables
DragonFS

DragonFS filesystem implementation and newlib hooks. More...

Data Structures

struct  directory_entry
 Representation of a directory entry. More...
struct  file_entry
 Representation of a file sector. More...
struct  open_file
 Open file handle structure. More...

Files

file  dragonfs.c
 

DragonFS.


file  dfsinternal.h
 

Internal DFS Definitions.


file  dragonfs.h
 

DragonFS.


Defines

#define FLAGS_ID   0xFFFFFFFF
 The special ID value in directory_entry::flags defining the master sector.
#define NEXTENTRY_ID   0xDEADBEEF
 The special ID value in directory_entry::next_entry defining the master sector.
#define SECTOR_SIZE   256
 The size of a sector.
#define SECTOR_PAYLOAD   252
 The size of a sector payload.
#define DFS_DEFAULT_LOCATION   0xB0101000
 Default filesystem location.
#define MAX_OPEN_FILES   4
 Maximum open files in DragonFS.
#define MAX_FILENAME_LEN   243
 Maximum filename length.
#define MAX_DIRECTORY_DEPTH   100
 Maximum depth of directories supported.
#define FILETYPE(x)   ((x) & 3)
 Macro to extract the file type from a DragonFS file flag.

Typedefs

typedef struct directory_entry directory_entry_t
 Type definition.
typedef struct file_entry file_entry_t
 Type definition.
typedef struct open_file open_file_t
 Open file handle structure.

Enumerations

enum  { WALK_CHDIR, WALK_OPEN }
 Directory walking flags. More...
enum  { TYPE_ANY, TYPE_FILE, TYPE_DIR }
 Directory walking return flags. More...

Functions

static void grab_sector (void *cart_loc, void *ram_loc)
 Read a sector from cartspace.
static open_file_tfind_free_file ()
 Find a free open file structure.
static open_file_tfind_open_file (uint32_t x)
 Find an open file structure based on a handle.
static int sector_from_loc (uint32_t loc)
 Look up a sector number based on offset.
static int offset_into_sector (uint32_t loc)
 Look up a byte offset into a sector.
static int data_left_in_sector (uint32_t loc)
 Look up the remaining data size in a sector.
static uint32_t get_flags (directory_entry_t *dirent)
 Return the file flags given a directory entry.
static uint32_t get_size (directory_entry_t *dirent)
 Return the file size given a directory entry.
static directory_entry_tget_first_entry (directory_entry_t *dirent)
 Get the directory pointer from a directory entry.
static directory_entry_tget_next_entry (directory_entry_t *dirent)
 Get the next directory entry.
static file_entry_tget_first_sector (directory_entry_t *dirent)
 Get the file pointer from a directory entry.
static file_entry_tget_next_sector (file_entry_t *fileent)
 Get the next file sector given a current file sector.
static void walk_sectors (open_file_t *file, uint32_t num_sectors)
 Walk forward in a file a specified number of sectors.
static void clear_directory ()
 Reset the directory stack to the root.
static void push_directory (directory_entry_t *dirent)
 Push a directory onto the stack.
static directory_entry_tpop_directory ()
 Pop a directory from the stack.
static directory_entry_tpeek_directory ()
 Peek at the top directory on the stack.
static char * get_next_token (char *path, char *token)
 Parse out the next token in a path delimited by '\'.
static directory_entry_tfind_dirent (char *name, directory_entry_t *cur_node)
 Find a directory node in the current path given a name.
static int recurse_path (const char *const path, int mode, directory_entry_t **dirent, int type)
 Walk a path string, either changing directories or finding the right path.
static int __dfs_init (uint32_t base_fs_loc)
 Helper functioner to initialize the filesystem.
int dfs_chdir (const char *const path)
 Change directories to the specified path.
int dfs_dir_findfirst (const char *const path, char *buf)
 Find the first file or directory in a directory listing.
int dfs_dir_findnext (char *buf)
 Find the next file or directory in a directory listing.
int dfs_open (const char *const path)
 Open a file given a path.
int dfs_close (uint32_t handle)
 Close an already open file handle.
int dfs_seek (uint32_t handle, int offset, int origin)
 Seek to an offset in the file.
int dfs_tell (uint32_t handle)
 Return the current offset into a file.
int dfs_read (void *const buf, int size, int count, uint32_t handle)
 Read data from a file.
int dfs_size (uint32_t handle)
 Return the file size of an open file.
int dfs_eof (uint32_t handle)
 Return whether the end of file has been reached.
static void * __open (char *name, int flags)
 Newlib-compatible open.
static int __fstat (void *file, struct stat *st)
 Newlib-compatible fstat.
static int __lseek (void *file, int ptr, int dir)
 Newlib-compatible lseek.
static int __read (void *file, uint8_t *ptr, int len)
 Newlib-compatible read.
static int __close (void *file)
 Newlib-compatible close.
static int __findfirst (char *path, dir_t *dir)
 Newlib-compatible findfirst.
static int __findnext (dir_t *dir)
 Newlib-compatible findnext.
int dfs_init (uint32_t base_fs_loc)
 Initialize the filesystem.

Variables

static uint32_t base_ptr = 0
 Base filesystem pointer.
static open_file_t open_files [MAX_OPEN_FILES]
 Open file tracking.
static uint32_t directories [MAX_DIRECTORY_DEPTH]
 Directory pointer stack.
static uint32_t directory_top = 0
 Depth into directory pointer stack.
static directory_entry_tnext_entry = 0
 Pointer to next directory entry set when doing a directory walk.
static filesystem_t dragon_fs
 Structure used for hooking DragonFS into newlib.

DragonFS Return values

#define DFS_ESUCCESS   0
 Success.
#define DFS_EBADINPUT   -1
 Input parameters invalid.
#define DFS_ENOFILE   -2
 File does not exist.
#define DFS_EBADFS   -3
 Bad filesystem.
#define DFS_ENOMEM   -4
 No memory for operation.
#define DFS_EBADHANDLE   -5
 Invalid file handle.

DragonFS file type flags

#define FLAGS_FILE   0x0
 This is a file entry.
#define FLAGS_DIR   0x1
 This is a directory entry.
#define FLAGS_EOF   0x2
 This is the end of a directory list.

Detailed Description

DragonFS filesystem implementation and newlib hooks.

DragonFS is a read only ROM filesystem for the N64. It provides an interface that homebrew developers can use to load resources from cartridge space that were not available at compile time. This can mean sprites or other game assets, or the filesystem can be appended at a later time if the homebrew developer wishes end users to be able to insert custom levels, music or other assets. It is loosely based off of FAT with consideration into application and limitations of the N64.

The filesystem can be generated using 'mkdfs' which is included in the 'tools' directory of libdragon. Due to the read-only nature, DFS does not support empty files or empty directories. Attempting to create a filesystem with either of these using 'mkdfs' will result in an error. If a filesystem contains either empty files or empty directories, the result of manipulating the filesystem is undefined.

DragonFS does not support writing, renaming or symlinking of files. It supports only file and directory types.

DFS files have a maximum size of 16,777,216 bytes. Directories can have an unlimited number of files in them. Each token (separated by a / in the path) can be 243 characters maximum. Directories can be 100 levels deep at maximum. There can be 4 files open simultaneously.

When DFS is initialized, it will register itself with newlib using 'rom:/' as a prefix. Files can be accessed either with standard POSIX functions and the 'rom:/' prefix or with DFS API calls and no prefix. Files can be opened using both sets of API calls simultaneously as long as no more than four files are open at any one time.


Define Documentation

#define DFS_DEFAULT_LOCATION   0xB0101000

Default filesystem location.

The default is 1MB into the ROM space, plus the header offset

#define FILETYPE (   x)    ((x) & 3)

Macro to extract the file type from a DragonFS file flag.

Parameters:
[in]xFile flags from DFS entry
Returns:
The file type flag
#define MAX_FILENAME_LEN   243

Maximum filename length.

This value is due to the direcory structure


Enumeration Type Documentation

anonymous enum

Directory walking flags.

Enumerator:
WALK_CHDIR 

Walk the directory structure for the purpose of changing directories.

WALK_OPEN 

Walk the directory structure for the purpose of opening a file or directory.

anonymous enum

Directory walking return flags.

Enumerator:
TYPE_ANY 

Return any file or directory found.

TYPE_FILE 

Return a file from directory walk.

TYPE_DIR 

Return a directory from a directory walk.


Function Documentation

static int __close ( void *  file) [static]

Newlib-compatible close.

Parameters:
[in]fileFile pointer as returned by __open
Returns:
0 on success or a negative error otherwise.
static int __dfs_init ( uint32_t  base_fs_loc) [static]

Helper functioner to initialize the filesystem.

Parameters:
[in]base_fs_locLocation of the filesystem
Returns:
DFS_ESUCCESS on successful initialization or a negative error on failure.
static int __findfirst ( char *  path,
dir_t dir 
) [static]

Newlib-compatible findfirst.

Parameters:
[in]pathAbsolute path of the directory to walk
[out]dirDirectory structure to populate with information on the first entry found
Returns:
0 on success or a negative value on failure.
static int __findnext ( dir_t dir) [static]

Newlib-compatible findnext.

Parameters:
[out]dirDirectory structure to populate with information on the next entry found
Returns:
0 on success or a negative value on failure.
static int __fstat ( void *  file,
struct stat st 
) [static]

Newlib-compatible fstat.

Parameters:
[in]fileFile pointer as returned by __open
[out]stStat structure to populate
Returns:
0.
static int __lseek ( void *  file,
int  ptr,
int  dir 
) [static]

Newlib-compatible lseek.

Parameters:
[in]fileFile pointer as returned by __open
[in]ptrOffset based on dir
[in]dirA direction to seek from. Either #SEEK_SET, #SEEK_CUR or #SEEK_END
Returns:
The new position in the file after the seek.
static void* __open ( char *  name,
int  flags 
) [static]

Newlib-compatible open.

Parameters:
[in]nameAbsolute path of the file to open
[in]flagsPOSIX file flags
Returns:
A newlib-compatible file handle.
static int __read ( void *  file,
uint8_t *  ptr,
int  len 
) [static]

Newlib-compatible read.

Parameters:
[in]fileFile pointer as returned by __open
[out]ptrPointer to buffer to read to
[in]lenLength in bytes to read
Returns:
The actual amount of data read.
static int data_left_in_sector ( uint32_t  loc) [inline, static]

Look up the remaining data size in a sector.

Given a byte offset from the start of a filesystem, this function will return the number of bytes from the current location to the end of the sector.

Parameters:
[in]locOffset in bytes
Returns:
The number of bytes left in a sector based on an offset
int dfs_chdir ( const char *const  path)

Change directories to the specified path.

Supports absolute and relative

Parameters:
[in]pathRelative or absolute path to change directories to
Returns:
DFS_ESUCCESS on success or a negative value on error.
int dfs_close ( uint32_t  handle)

Close an already open file handle.

Parameters:
[in]handleA valid file handle as returned from dfs_open.
Returns:
DFS_ESUCCESS on success or a negative value on error.
int dfs_dir_findfirst ( const char *const  path,
char *  buf 
)

Find the first file or directory in a directory listing.

Supports absolute and relative. If the path is invalid, returns a negative DFS_errno. If a file or directory is found, returns the flags of the entry and copies the name into buf.

Parameters:
[in]pathThe path to look for files in
[out]bufBuffer to place the name of the file or directory found
Returns:
The flags (FLAGS_FILE, FLAGS_DIR, FLAGS_EOF) or a negative value on error.
int dfs_dir_findnext ( char *  buf)

Find the next file or directory in a directory listing.

Note:
Should be called after doing a dfs_dir_findfirst.
Parameters:
[out]bufBuffer to place the name of the next file or directory found
Returns:
The flags (FLAGS_FILE, FLAGS_DIR, FLAGS_EOF) or a negative value on error.
int dfs_eof ( uint32_t  handle)

Return whether the end of file has been reached.

Parameters:
[in]handleA valid file handle as returned from dfs_open.
Returns:
1 if the end of file is reached, 0 if not, and a negative value on error.
int dfs_init ( uint32_t  base_fs_loc)

Initialize the filesystem.

Given a base offset where the filesystem should be found, this function will initialize the filesystem to read from cartridge space. This function will also register DragonFS with newlib so that standard POSIX file operations work with DragonFS.

Parameters:
[in]base_fs_locMemory mapped location at which to find the filesystem. This is normally 0xB0000000 + the offset used when building your ROM + the size of the header file used.
Returns:
DFS_ESUCCESS on success or a negative error otherwise.
int dfs_open ( const char *const  path)

Open a file given a path.

Check if we have any free file handles, and if we do, try to open the file specified. Supports absolute and relative paths

Parameters:
[in]pathPath of the file to open
Returns:
A valid file handle to reference the file by or a negative error on failure.
int dfs_read ( void *const  buf,
int  size,
int  count,
uint32_t  handle 
)

Read data from a file.

Parameters:
[out]bufBuffer to read into
[in]sizeSize of each element to read
[in]countNumber of elements to read
[in]handleA valid file handle as returned from dfs_open.
Returns:
The actual number of bytes read or a negative value on failure.
int dfs_seek ( uint32_t  handle,
int  offset,
int  origin 
)

Seek to an offset in the file.

Parameters:
[in]handleA valid file handle as returned from dfs_open.
[in]offsetA byte offset from the origin to seek from.
[in]originAn offset to seek from. Either #SEEK_SET, #SEEK_CUR or #SEEK_END.
Returns:
DFS_ESUCCESS on success or a negative value on error.
int dfs_size ( uint32_t  handle)

Return the file size of an open file.

Parameters:
[in]handleA valid file handle as returned from dfs_open.
Returns:
The file size in bytes or a negative value on failure.
int dfs_tell ( uint32_t  handle)

Return the current offset into a file.

Parameters:
[in]handleA valid file handle as returned from dfs_open.
Returns:
The current byte offset into a file or a negative error on failure.
static directory_entry_t* find_dirent ( char *  name,
directory_entry_t cur_node 
) [static]

Find a directory node in the current path given a name.

Parameters:
[in]nameName of the file or directory in question
[in]cur_nodeDirectory entry to start search from
Returns:
The directory entry matching the name requested or NULL if not found.
static open_file_t* find_free_file ( ) [static]

Find a free open file structure.

Returns:
A pointer to an open file structure or NULL if no more open file structures.
static open_file_t* find_open_file ( uint32_t  x) [static]

Find an open file structure based on a handle.

Parameters:
[in]xThe file handle given to the open file
Returns:
A pointer to an open file structure or NULL if no file matches the handle
static directory_entry_t* get_first_entry ( directory_entry_t dirent) [inline, static]

Get the directory pointer from a directory entry.

This function is used to grab the first directory entry of a subdirectory given the current directory pointer.

Parameters:
[in]direntDirectory entry to retrieve directory pointer from
Returns:
A pointer to the directory represented by the directory entry.
static file_entry_t* get_first_sector ( directory_entry_t dirent) [inline, static]

Get the file pointer from a directory entry.

This function is used to grab the first sector of a file given the current directory pointer.

Parameters:
[in]direntDirectory entry to retrieve file pointer from
Returns:
A pointer to the first sector of a file.
static uint32_t get_flags ( directory_entry_t dirent) [inline, static]

Return the file flags given a directory entry.

Parameters:
[in]direntDirectory entry to retrieve flags from
Returns:
The flags portion of a directory entry
static directory_entry_t* get_next_entry ( directory_entry_t dirent) [inline, static]

Get the next directory entry.

Parameters:
[in]direntDirectory entry to retrieve next entry from
Returns:
A pointer to the next directory entry after the current directory entry.
static file_entry_t* get_next_sector ( file_entry_t fileent) [inline, static]

Get the next file sector given a current file sector.

Parameters:
[in]fileentFile entry structure to retrieve next sector from
Returns:
A pointer to the next sector of a file.
static char* get_next_token ( char *  path,
char *  token 
) [static]

Parse out the next token in a path delimited by '\'.

Parameters:
[in]pathCurrent path to extract next token from
[out]tokenString buffer to place the extracted token
Returns:
The rest of path that was not parsed.
static uint32_t get_size ( directory_entry_t dirent) [inline, static]

Return the file size given a directory entry.

Parameters:
[in]direntDirectory entry to retrieve size from
Returns:
The size of the file represented by the directory entry
static void grab_sector ( void *  cart_loc,
void *  ram_loc 
) [inline, static]

Read a sector from cartspace.

This function handles fetching a sector from cartspace into RDRAM using DMA.

Parameters:
[in]cart_locPointer to cartridge location
[out]ram_locPointer to RAM buffer to place the read sector
static int offset_into_sector ( uint32_t  loc) [inline, static]

Look up a byte offset into a sector.

Given a byte offset from the start of a filesystem, this function will return the offset into the current sector. This essentially clamps the ouput from 0 to SECTOR_PAYLOAD.

Parameters:
[in]locOffset in bytes
Returns:
The offset into a sector
static directory_entry_t* peek_directory ( ) [inline, static]

Peek at the top directory on the stack.

Returns:
The directory entry on the top of the stack
static directory_entry_t* pop_directory ( ) [inline, static]

Pop a directory from the stack.

Returns:
The directory entry on the top of the stack
static void push_directory ( directory_entry_t dirent) [inline, static]

Push a directory onto the stack.

Parameters:
[in]direntDirectory entry to push onto the stack
static int recurse_path ( const char *const  path,
int  mode,
directory_entry_t **  dirent,
int  type 
) [static]

Walk a path string, either changing directories or finding the right path.

If mode is WALK_CHDIR, the result of this function is entering into the new directory on success, or the old directory being returned on failure.

If mode is WALK_OPEN, the result of this function is the directory remains unchanged and a pointer to the directory entry for the requested file or directory is returned. If it is a file, the directory entry for the file itself is returned. If it is a directory, the directory entry of the first file or directory inside that directory is returned.

The type specifier allows a person to specify that only a directory or file should be returned. This works for WALK_OPEN only.

Parameters:
[in]pathThe path to walk through
[in]modeEither WALK_CHDIR or WALK_OPEN.
[in,out]direntDirectory entry to start at, directory entry finished at
[in]typeEither TYPE_ANY, TYPE_FILE, or TYPE_DIR.
Returns:
DFS_ESUCCESS on successful recurse, or a negative error on failure.
static int sector_from_loc ( uint32_t  loc) [inline, static]

Look up a sector number based on offset.

Given a byte offset from the start of a filesystem, this function will return the sector that this byte offset falls into.

Parameters:
[in]locOffset in bytes
Returns:
The sector number corresponding to the offset
static void walk_sectors ( open_file_t file,
uint32_t  num_sectors 
) [static]

Walk forward in a file a specified number of sectors.

Parameters:
[in]fileOpen file structure
[in]num_sectorsNumber of sectors to advance the file

Variable Documentation

Initial value:

Structure used for hooking DragonFS into newlib.

The following section of code is for bridging into newlib's filesystem hooks to allow posix access to DragonFS filesystem.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines