FBFS File System
Up until now, FPGABee supported only a single virtual disk image at block 0 on the SD card. The first step in supporting multiple disk images and multiple drives is to design a file system format to store those images and a implement a utility for manipulating the file system.
The FBFS File System
FBFS (for FpgaBee File System) is a simple file system that supports storing multiple files and guarantees that files are stored in a contiguous, non-fragmented way. It doesn't support directories but it does support a mechanism for store which disk is in which drive.
The basic structure of the file system is this:
- Block 0 - the config sector
- Block 1-N - a set of directory entries
- Block N+1 to end of disk - file data.
The config sector stores a single FBFS_CONFIG record:
#define NUM_DRIVE_SLOTS 7
#define NUM_ROM_SLOTS 3
struct CONFIG
{
uint32_t signature; // Signature identifying file system - "fbfs"
uint16_t version; // fbfs version - 0x0100
uint32_t dir_block; // first directory block
uint16_t dir_block_count; // directory block count
uint16_t system_image; // dirid the system image
uint16_t rom_images[NUM_ROM_SLOTS]; // dirid to 3 rom images (pak A, B, C)
uint16_t disk_images[NUM_DRIVE_SLOTS]; // dirids to selected disk images
};
The signature
and version
fields are self explanatory. The fields dir_block
and dir_block_count
specify the range of blocks that hold the directory entries. The last field disk_images
specifies the index of the directory entry for the disk images that are selected for each of the disk controller's 7 possible drives. The remaining two fields system_image
and rom_images
aren't used yet but are placeholders for things that will be needed later.
A directory entry is defined as follows:
struct DIRENTRY
{
uint32_t block; // Starting block number
uint16_t block_count; // Block count
uint32_t resvd; // Reserved
char filename[22]; // File name, space padded
};
It's a simple structure and is self explanatory - a range of blocks that the file's data occupies and a null-terminated filename - a filename can be a maximum of 21 characters plus the null.
A directory entry is exactly 32 bytes in length and each directory block therefore can store 16 directory entries. Deleted files are indicated by a non-zero block number and a zero-length filename. The first directory entry after all used directory entries has the block field set to 0 - to indicate no further entries will be found and processing need not continue.
The fbfs
Utility
To manipulate this file system I wrote a simple command line tool - fbfs
:
C:\>fbfs --help
fbfs v1.0 - FPGABee File System Utility
Copyright (C) 2013 Topten Software. All Rights Reserved
Usage: fbfs <fsimage> <command> [args]
fsimage image of the fbfs file system to work with
command see commands below
args additional command argument
Commands:
format create a new fbfs file system
ls [<spec>] list files in fsimage
add <file> [newname] add file to fsimage
extract <file> [<diskimage>] extract file from fsimage
mv <oldfile> <newfile> rename file in fsimage
rm <file> remove file from fsimage
select system <file> specify file containing PCU sys image
select disk <drive> <file> insert disk image into drive
select rom <pak> <file> insert rom into pak slot
select display selected system, rom and disks
transfer <newimage> transfer entire file system to newimage
fbfs
can work with either a physical SD card drive, or a normal file system file to create an image. To create a new file system use the format command:
c:\>fbfs f: format
or if working with an image file:
c:\>fbfs c:\fbgabee\my_sd_image.fbfs format
Most of the commands are self explanatory, but here's an example of how a typical image would be created:
fbfs myfs.fbfs format
fbfs myfs.fbfs add hd.hd0
fbfs myfs.fbfs add HDPREM1.ds40
fbfs myfs.fbfs add HDPREM2.ds40
fbfs myfs.fbfs select disk 1 hd.hd0
fbfs myfs.fbfs select disk 3 HDPREM1.ds40
fbfs myfs.fbfs select disk 4 HDPREM2.ds40
fbfs myfs.fbfs ls
fbfs myfs.fbfs select
The other useful feature of fbfs is that it can copy to/from the physical SD card, avoiding the need for other raw-write tools. For example:
fbfs myfs.fbfs transfer k:
The transfer command creates a new image, copies files within the source image and then sets up the same selected images - effectively removing holes caused by deleted files.
Currently fbfs only runs on Windows, but was implemented in standard C++ and should port easily to other platforms.
Accessing Multiple Disks in FPGABee
Before adding full support for multiple disks to FPGABee, I decided to test what I had so far by hard-coding the offsets to three files (1 HDD image and 2 FDD images) into the disk controller. The ls
command lists the block number of each file:
C:\retro\ubee512\disks>fbfs myimage.fbfs ls
blk# blks size filename
----------------------------------------------------
9 20808 10653696 hd.hd0
20817 800 409600 HDPREMD1.DS40
21617 800 409600 HDPREMD2.DS40
Total 3 files
I converted the block numbers to hex and updating the disk controller:
case reg_drive is
when "001" =>
-- HDD1
geo_disk_type <= DISK_HD0;
diskimage_base_cluster <= x"00000009";
when "100" =>
-- FDD 1
geo_disk_type <= DISK_DS40;
diskimage_base_cluster <= x"00005151"; -- 20817
when "101" =>
-- FDD 1
geo_disk_type <= DISK_DS40;
diskimage_base_cluster <= x"00005471"; -- 21617
and multiple disk support was basically working.
The next step is to figure out a mechanism for configuring the disk controller based on what's on the SD card and providing a way for the user to switch floppy drive images.