#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define INT8    char
#define INT16   short
#define INT32   long
#define UINT8   unsigned char
#define UINT16  unsigned short
#define UINT32  unsigned long
#define INT     int
#define UINT    unsigned int
#define FLOAT32 float
#define FLOAT64 double

#define SDRAM_BASE			0x40000000
#define	FLASH_OFFSET		0x00000000

#define	MAGIC_EB	0x4A464931	// "JFI1" in big-endian;
#define	MAGIC_EL	0x3149464A	// "JFI1" in little-endian;

UINT32 conv_endian32(UINT32 src)
{
	UINT32 dst;

	dst = (0xFF000000 & (src << 24))
		| (0x00FF0000 & (src << 8))
		| (0x0000FF00 & (src >> 8))
		| (0x000000FF & (src >> 24));

	return dst;
};

// --------------------------------------------------------------
typedef struct _sflash_img_hdr_t
{
	UINT32 magic;
	UINT32 target_addr;
	UINT32 img_offset;
	UINT32 img_size;
	UINT32 hdr_next;
	UINT8 img_name[128];
	UINT8 res[108];

} flash_img_hdr_t;

// --------------------------------------------------------------
void basename(char *pSrc, char *pDst)
{
	int i, size;

	size = strlen(pSrc);

	while(pSrc[size] != '.')
		size--;

	for (i=0; i < size; i++)
		pDst[i] = pSrc[i];

	pDst[i] = 0;

}

// --------------------------------------------------------------
int main(int argc, char *argv[])
{
	char *pFilenameIn;
	char name_flash[1024];
	char name_prj[1024];
	char *pBuf;
	UINT32 *pBuf32;
	flash_img_hdr_t img_hdr = {0};

	FILE *pFile;
	int filesize;
	long start, end;
	int i;

	if (argc < 2)
	{
		fprintf(stderr, "Usage: flashgen <input file> [-{EL|EB}]\n");
		return 1;
	}

	pFilenameIn = argv[1];
	pFile = fopen(pFilenameIn, "rb");
	if (!pFile)
	{
		fprintf(stderr, "Error opening file %s\n", pFilenameIn);
		return 1;
	}

	basename(pFilenameIn, name_prj);
	sprintf(name_flash, "%s.flash.bin", name_prj);

	// determine filesize
	fseek(pFile, 0, SEEK_SET);
	start = ftell(pFile);
	fseek(pFile, 0, SEEK_END);
	end = ftell(pFile);
	fseek(pFile, 0, SEEK_SET);
	filesize = (end-start);

	pBuf = (char*)malloc(filesize);
	fread(pBuf, 1, filesize, pFile);

	fclose(pFile);

	pFile = fopen(name_flash, "wb");
	if (!pFile)
	{
		fprintf(stderr, "Error opening file %s\n", name_flash);
		return 1;
	}

	img_hdr.magic = MAGIC_EL;
	img_hdr.target_addr = SDRAM_BASE;
	img_hdr.img_size = filesize;
	img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
	img_hdr.hdr_next = FLASH_OFFSET;

	if (argc == 3)
	{
		if ((argv[2][0] == '-') && (toupper(argv[2][1]) == 'E') && (toupper(argv[2][2]) == 'B'))
		{
			img_hdr.magic = MAGIC_EB;
			pBuf32 = (UINT32*)pBuf;
			for (i=0; i < filesize/4; i ++)
				pBuf32[i] = conv_endian32(pBuf32[i]);
		}
	}
	fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
	fwrite(pBuf, 1, filesize, pFile);

	fclose(pFile);

	return 0;
}

