summaryrefslogtreecommitdiff
path: root/mkfs.ffs2.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkfs.ffs2.c')
-rw-r--r--mkfs.ffs2.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/mkfs.ffs2.c b/mkfs.ffs2.c
new file mode 100644
index 0000000..36204dd
--- /dev/null
+++ b/mkfs.ffs2.c
@@ -0,0 +1,239 @@
+// Description
+// $Id: mkfs.ffs2.c,v 1.5 2005/11/07 11:15:12 gleixner Exp $
+/* ######################################################################
+
+ Microsoft Flash File System 2
+
+ Information for the FFS2.0 was found in Microsoft's knowledge base,
+ http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/specs/S346A.HTM
+ Try searching for "Flash File System" if it has been moved
+
+ This program creates an empty file system.
+
+ ##################################################################### */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+
+#include <mtd/mtd-user.h"
+#include <linux/ffs2_fs.h"
+
+static unsigned long BlockSize = 128*1024;
+static int Fd;
+
+// Erase a single block
+int EraseBlock(unsigned Number)
+{
+ unsigned char Blank[512];
+ unsigned I;
+
+ memset(Blank,0xFF,sizeof(Blank));
+
+ if (lseek(Fd,BlockSize*Number,SEEK_SET) != BlockSize*Number)
+ return -1;
+
+ for (I = 0; I*sizeof(Blank) != BlockSize; I++)
+ {
+ if (write(Fd,Blank,sizeof(Blank)) != sizeof(Blank))
+ return -1;
+ }
+
+ return 0;
+}
+
+int main (int argc,char * const argv[])
+{
+ struct mtd_info meminfo;
+ unsigned Device;
+ unsigned int Opt;
+ unsigned I;
+ unsigned long Length;
+ unsigned long Spares = 1;
+ unsigned long Start = 0;
+
+ // Process options
+ while ((Opt = getopt(argc,argv,"b:s:")) != EOF)
+ {
+ switch (Opt)
+ {
+ case 'b':
+ BlockSize = strtol(optarg, NULL, 0);
+ break;
+
+ case 's':
+ Start = strtol(optarg, NULL, 0);
+ break;
+
+ case '?':
+ return 16;
+ }
+ }
+
+ // Find the device name
+ Device = optind;
+ for (;Device < argc && (argv[Device][0] == 0 ||
+ argv[Device][0] == '-'); Device++);
+ if (Device >= argc)
+ {
+ fprintf(stderr,"You must specify a device\n");
+ return 16;
+ }
+
+ // Open and size the device
+ if ((Fd = open(argv[Device],O_RDWR)) < 0)
+ {
+ fprintf(stderr,"File open error\n");
+ return 8;
+ }
+ if (ioctl(Fd,BLKGETSIZE,&Length) < 0)
+ {
+ Length = lseek(Fd,0,SEEK_END);
+ lseek(Fd,0,SEEK_SET);
+ }
+ else
+ Length *= 512;
+
+ if ((Start + 1)*BlockSize > Length)
+ {
+ fprintf(stderr,"The flash is not large enough\n");
+ }
+
+ printf("Total size is %lu, %lu byte erase "
+ "blocks for %lu blocks with %lu spares.\n",Length,BlockSize,
+ Length/BlockSize,Spares);
+ if (Start != 0)
+ printf("Skiping the first %lu bytes\n",Start*BlockSize);
+
+ if (ioctl(Fd,MEMGETINFO,&meminfo) == 0)
+ {
+ struct erase_info erase;
+ printf("Performing Flash Erase");
+ fflush(stdout);
+
+ erase.length = Length - Start*BlockSize;
+ erase.start = Start*BlockSize;
+ if (ioctl(Fd,MEMERASE,&erase) != 0)
+ {
+ perror("\nMTD Erase failure");
+ close(Fd);
+ return 8;
+ }
+ printf(" done\n");
+ }
+ else
+ {
+ for (I = Start; I <= Length/BlockSize; I++)
+ {
+ printf("Erase %u\r",I);
+ fflush(stdout);
+ if (EraseBlock(I) != 0)
+ {
+ perror(argv[Device]);
+ close(Fd);
+ return 8;
+ }
+ }
+ }
+
+ for (I = 0; I != Length/BlockSize; I++)
+ {
+ struct ffs2_block block;
+
+ // Write the block structure
+ memset(&block,0xFF,sizeof(block));
+ block.EraseCount = 1;
+ block.BlockSeq = I;
+ block.BlockSeqChecksum = 0xFFFF ^ block.BlockSeq;
+ block.Status = (block.Status & (~FFS_STATE_MASK)) | FFS_STATE_READY;
+
+ // Is Spare
+ if (I >= Length/BlockSize - Spares)
+ {
+ block.BlockSeq = 0xFFFF;
+ block.BlockSeqChecksum = 0xFFFF;
+ block.Status = (block.Status & (~FFS_STATE_MASK)) | FFS_STATE_SPARE;
+ }
+
+ // Setup the boot record and the root record
+ if (I == 0)
+ {
+ struct ffs2_bootrecord boot;
+ struct ffs2_blockalloc alloc[2];
+ unsigned char Tmp[300];
+ struct ffs2_entry *root = (struct ffs2_entry *)Tmp;
+
+ block.BootRecordPtr = 0;
+ block.Status = (block.Status & (~FFS_BOOTP_MASK)) | FFS_BOOTP_CURRENT;
+
+ boot.Signature = 0xF1A5;
+ boot.SerialNumber = time(0);
+ boot.FFSWriteVersion = 0x200;
+ boot.FFSReadVersion = 0x200;
+ boot.TotalBlockCount = Length/BlockSize;
+ boot.SpareBlockCount = Spares;
+ boot.BlockLen = BlockSize;
+ boot.RootDirectoryPtr = 0x1;
+ boot.BootCodeLen = 0;
+
+ memset(root,0xFF,sizeof(*root));
+ root->Status = (root->Status & (~FFS_ENTRY_TYPEMASK)) | FFS_ENTRY_TYPEDIR;
+ root->NameLen = strlen("root");
+ root->Time = (__u16)boot.SerialNumber;
+ root->Date = (__u16)(boot.SerialNumber >> 16);
+ root->VarStructLen = 0;
+ strcpy(root->Name,"root");
+
+ // Boot Block allocation structure
+ alloc[1].Status = (0xFF & (~FFS_ALLOC_SMASK)) | FFS_ALLOC_ALLOCATED;
+ alloc[1].Status &= 0xFF & (~FFS_ALLOC_EMASK);
+ alloc[1].Offset[0] = 0;
+ alloc[1].Offset[1] = 0;
+ alloc[1].Offset[2] = 0;
+ alloc[1].Len = FFS_SIZEOF_BOOT;
+
+ // Root Dir allocation structure
+ alloc[0].Status = (0xFF & (~FFS_ALLOC_SMASK)) | FFS_ALLOC_ALLOCATED;
+ alloc[0].Offset[0] = FFS_SIZEOF_BOOT;
+ alloc[0].Offset[1] = 0;
+ alloc[0].Offset[2] = 0;
+ alloc[0].Len = FFS_SIZEOF_ENTRY + root->NameLen;
+
+ // Write the two headers
+ if (lseek(Fd,BlockSize*(I+Start),SEEK_SET) < 0 ||
+ write(Fd,&boot,FFS_SIZEOF_BOOT) != FFS_SIZEOF_BOOT ||
+ write(Fd,root,FFS_SIZEOF_ENTRY + root->NameLen) != FFS_SIZEOF_ENTRY + root->NameLen)
+ {
+ perror("Failed writing headers");
+ close(Fd);
+ return 8;
+ }
+
+ // And the two allocation structures
+ if (lseek(Fd,BlockSize*(I+Start+1) - FFS_SIZEOF_BLOCK - sizeof(alloc),
+ SEEK_SET) <= 0 ||
+ write(Fd,alloc,sizeof(alloc)) != sizeof(alloc))
+ {
+ perror("Failed writing allocations");
+ close(Fd);
+ return 8;
+ }
+ }
+
+ if (lseek(Fd,BlockSize*(I+Start+1) - FFS_SIZEOF_BLOCK,
+ SEEK_SET) <= 0 ||
+ write(Fd,&block,FFS_SIZEOF_BLOCK) != FFS_SIZEOF_BLOCK)
+ {
+ perror("Failed writing block");
+ close(Fd);
+ return 8;
+ }
+ }
+ printf("\n");
+
+ return 0;
+}