#!/usr/bin/python

# jdeigerfs v0.1
# (C)2005 John D. Rowell
# Licensed under the GPL v2

import os, string, sys

HEADER_SIZE = 512
BLOCK_SIZE = 4096
FLASH_MB = 1003520

files = sys.argv[1:]

if not files:
	print "Syntax: %s <file1> [<file2>] ..." % sys.argv[0]
	sys.exit(0)

def flashSeq(f_out):

	pos = 0

	for i in range(0, 128):
		seq = 1
		for j in range(0, 512):
			binseq = seq
			if binseq < 0:
				binseq += 256
			if binseq > 255:
				binseq -= 256
	
			f_out.write(chr(binseq))
			
			pos += 1
		
			adji = i
			if pos % 1024 == 1021:
			  adji += 1
			elif (pos % 1024 == 3) and (i != 0):
			  adji -= 1
		  
		  	f_out.write(chr(adji))

			pos += 1
		
			if j % 2:
				seq = seq + 3
			else:
				seq = seq - 2

	f_out.write('\xFF' * 4096)

	return

def tagFAT(f_out, start, length, fileindex):

	tag_start = (start / 1024) + 2
	print "Tagging file start at %08X" % tag_start
	f_out.seek(tag_start)
	f_out.write('\x01\x00')

	tag_end = ((start + length) / 1024) 
	print "Tagging file end at %08X" % tag_end
	f_out.seek(tag_end)
	f_out.write('\xFE\xFF')

	tag_startblock = '%04X' % (start / 4096)
	print "Tagging file start block as %s" % tag_startblock
	f_out.seek(int('0x20000', 16) + (fileindex - 1) * 2)
	f_out.write(chr(int(tag_startblock[2:4],16)) + chr(int(tag_startblock[0:2],16)))

	f_out.seek(0, 2)

	return

def tagDigest(f_out, fcount):

	FILECOUNT_POS = int('0x0001F000', 16)

	print "Tagging flash with file count: %d" % fcount

	f_out.seek(FILECOUNT_POS)
	f_out.write('\x05\x01\x01\x03\x00\x00')
	f_out.write(chr(fcount))

	return
	
def setFS(f_out):
	
	f_out.seek(0)
	for s in ('Eiger M&C MMC File System Ver. 1.00\x00\x00',
		'\x00\x00\x00\x36',
		'\x00\x00\x00\x08',
		'\x00\x00\x00\x03',
		'\x00\x00\x00\x08', 
		'\x00\x00\x00\x02', 
		'\x00\x00\x00\x69', 
		'\x00\x00\x00\x02', 
		'\x00\x00\x00\x42', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x00', 
		'\x00\x00\x00\x08', 
		'\x00\x00\x00\x22'):
		f_out.write(s)

	#f_out.seek(int('0x00013600', 16))
	#f_out.write('\xF8\xFF\xFF\xFF')

	#f_out.seek(int('0x0001F1F4', 16))
	#f_out.write('\x77')
	
	return

def writeFile(f_out, path, fileindex):

	if not '/' in path:
		filename = path
	else:
		filename = path[string.rfind(path, '/')+1:]

	h_filename = filename + '\x00' * (256 - len(filename))

	size = os.stat(path)[6]
	sizehex = '%016x' % size
	h_size = ''

	tagFAT(f_out, f_out.tell(), size, fileindex)

	# put file size in little endian format
	for i in range(8, 0, -1):
		h_size += chr(int(sizehex[i*2-2:i*2], 16))

	h_size += '\x00' * 248

	f_out.write(h_filename)
	f_out.write(h_size)

	print "Writing '%s', %d bytes\n" % (filename, size)

	f_in = open(path)

	while 1:
		buf = f_in.read(BLOCK_SIZE)
		f_out.write(buf)
		if len(buf) != BLOCK_SIZE:
			pad = BLOCK_SIZE - HEADER_SIZE - len(buf)
			if pad < 0:
				pad += BLOCK_SIZE
			f_out.write('\x00' * pad)
			break

	f_in.close()

	return

f_out = open('mm.img', 'w')

flashSeq(f_out)

fileindex = 0

for f in files:
	fileindex += 1
	writeFile(f_out, f, fileindex)

print "Minimum flash size is %dMB" % (f_out.tell() / FLASH_MB)
tagDigest(f_out, len(files))
setFS(f_out)

f_out.close()

