/*
 * rfddump.c
 *
 * Copyright (C) 2005 Sean Young <sean@mess.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 */

#define _XOPEN_SOURCE 500 /* For pread */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>

#include <mtd/mtd-user.h>
#include <linux/types.h>
#include <mtd_swab.h>

/* next is an array of mapping for each corresponding sector */
#define RFD_MAGIC		0x9193
#define HEADER_MAP_OFFSET       3
#define SECTOR_DELETED          0x0000
#define SECTOR_ZERO             0xfffe
#define SECTOR_FREE             0xffff

#define SECTOR_SIZE             512

#define SECTORS_PER_TRACK	63


struct rfd {
	int block_size;
	int block_count;
	int header_sectors;
	int data_sectors;
	int header_size;
	uint16_t *header;
	int sector_count;
	int *sector_map;
	const char *mtd_filename;
	const char *out_filename;
	int verbose;
};

#define PROGRAM "rfddump"
#define VERSION "$Revision 1.0 $"

void display_help(void)
{
	printf("Usage: " PROGRAM " [OPTIONS] MTD-device filename\n"
			"Dumps the contents of a resident flash disk\n"
			"\n"
			"-h         --help               display this help and exit\n"
			"-V         --version            output version information and exit\n"
			"-v         --verbose		Be verbose\n"
			"-b size    --blocksize          Block size (defaults to erase unit)\n");
	exit(0);
}

void display_version(void)
{
	printf(PROGRAM " " VERSION "\n"
			"\n"
			"This is free software; see the source for copying conditions.  There is NO\n"
			"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");

	exit(0);
}

void process_options(int argc, char *argv[], struct rfd *rfd)
{
	int error = 0;

	rfd->block_size = 0;
	rfd->verbose = 0;

	for (;;) {
		int option_index = 0;
		static const char *short_options = "hvVb:";
		static const struct option long_options[] = {
			{ "help", no_argument, 0, 'h' },
			{ "version", no_argument, 0, 'V', },
			{ "blocksize", required_argument, 0, 'b' },
			{ "verbose", no_argument, 0, 'v' },
			{ NULL, 0, 0, 0 }
		};

		int c = getopt_long(argc, argv, short_options,
				long_options, &option_index);
		if (c == EOF)
			break;

		switch (c) {
			case 'h':
				display_help();
				break;
			case 'V':
				display_version();
				break;
			case 'v':
				rfd->verbose = 1;
				break;
			case 'b':
				rfd->block_size = atoi(optarg);
				break;
			case '?':
				error = 1;
				break;
		}
	}

	if ((argc - optind) != 2 || error)
		display_help();

	rfd->mtd_filename = argv[optind];
	rfd->out_filename = argv[optind + 1];
}

int build_block_map(struct rfd *rfd, int fd, int block)
{
	int  i;
	int sectors;

	if (pread(fd, rfd->header, rfd->header_size, block * rfd->block_size)
			!= rfd->header_size) {
		return -1;
	}

	if (le16_to_cpu(rfd->header[0]) != RFD_MAGIC) {
		if (rfd->verbose)
			printf("Block #%02d: Magic missing\n", block);

		return 0;
	}

	sectors =  0;
	for (i=0; i<rfd->data_sectors; i++) {
		uint16_t entry = le16_to_cpu(rfd->header[i + HEADER_MAP_OFFSET]);

		if (entry == SECTOR_FREE || entry == SECTOR_DELETED)
			continue;

		if (entry == SECTOR_ZERO)
			entry = 0;

		if (entry >= rfd->sector_count) {
			fprintf(stderr, "%s: warning: sector %d out of range\n",
					rfd->mtd_filename, entry);
			continue;
		}

		if (rfd->sector_map[entry] != -1) {
			fprintf(stderr, "%s: warning: more than one entry "
					"for sector %d\n", rfd->mtd_filename, entry);
			continue;
		}

		rfd->sector_map[entry] = rfd->block_size * block +
			(i + rfd->header_sectors) * SECTOR_SIZE;
		sectors++;
	}

	if (rfd->verbose)
		printf("Block #%02d: %d sectors\n", block, sectors);

	return 1;
}

int main(int argc, char *argv[])
{
	int fd, sectors_per_block;
	mtd_info_t mtd_info;
	struct rfd rfd;
	int i, blocks_found;
	int out_fd = 0;
	uint8_t sector[512];
	int blank, rc, cylinders;

	process_options(argc, argv, &rfd);

	fd = open(rfd.mtd_filename, O_RDONLY);
	if (fd == -1) {
		perror(rfd.mtd_filename);
		return 1;
	}

	if (rfd.block_size == 0) {
		if (ioctl(fd, MEMGETINFO, &mtd_info)) {
			perror(rfd.mtd_filename);
			close(fd);
			return 1;
		}

		if (mtd_info.type != MTD_NORFLASH) {
			fprintf(stderr, "%s: wrong type\n", rfd.mtd_filename);
			close(fd);
			return 2;
		}

		sectors_per_block = mtd_info.erasesize / SECTOR_SIZE;

		rfd.block_size = mtd_info.erasesize;
		rfd.block_count = mtd_info.size / mtd_info.erasesize;
	} else {
		struct stat st;

		if (fstat(fd, &st) == -1) {
			perror(rfd.mtd_filename);
			close(fd);
			return 1;
		}

		if (st.st_size % SECTOR_SIZE)
			fprintf(stderr, "%s: warning: not a multiple of sectors (512 bytes)\n", rfd.mtd_filename);

		sectors_per_block = rfd.block_size / SECTOR_SIZE;

		if (st.st_size % rfd.block_size)
			fprintf(stderr, "%s: warning: not a multiple of block size\n", rfd.mtd_filename);

		rfd.block_count = st.st_size / rfd.block_size;

		if (!rfd.block_count) {
			fprintf(stderr, "%s: not large enough for one block\n", rfd.mtd_filename);
			close(fd);
			return 2;
		}
	}

	rfd.header_sectors =
		((HEADER_MAP_OFFSET + sectors_per_block) *
		 sizeof(uint16_t) + SECTOR_SIZE - 1) / SECTOR_SIZE;
	rfd.data_sectors = sectors_per_block - rfd.header_sectors;
	cylinders = ((rfd.block_count - 1) * rfd.data_sectors - 1)
		/ SECTORS_PER_TRACK;
	rfd.sector_count = cylinders * SECTORS_PER_TRACK;
	rfd.header_size =
		(HEADER_MAP_OFFSET + rfd.data_sectors) * sizeof(uint16_t);

	rfd.header = malloc(rfd.header_size);
	if (!rfd.header) {
		perror(PROGRAM);
		close(fd);
		return 2;
	}
	rfd.sector_map = malloc(rfd.sector_count * sizeof(int));
	if (!rfd.sector_map) {
		perror(PROGRAM);
		close(fd);
		free(rfd.sector_map);
		return 2;
	}

	rfd.mtd_filename = rfd.mtd_filename;

	for (i=0; i<rfd.sector_count; i++)
		rfd.sector_map[i] = -1;

	for (blocks_found=i=0; i<rfd.block_count; i++) {
		rc = build_block_map(&rfd, fd, i);
		if (rc > 0)
			blocks_found++;
		if (rc < 0)
			goto err;
	}

	if (!blocks_found) {
		fprintf(stderr, "%s: no RFD blocks found\n", rfd.mtd_filename);
		goto err;
	}

	for (i=0; i<rfd.sector_count; i++) {
		if (rfd.sector_map[i] != -1)
			break;
	}

	if (i == rfd.sector_count) {
		fprintf(stderr, "%s: no sectors found\n", rfd.mtd_filename);
		goto err;
	}

	out_fd = open(rfd.out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
	if (out_fd == -1) {
		perror(rfd.out_filename);
		goto err;
	}

	blank = 0;
	for (i=0; i<rfd.sector_count; i++) {
		if (rfd.sector_map[i] == -1) {
			memset(sector, 0, SECTOR_SIZE);
			blank++;
		} else {
			if (pread(fd, sector, SECTOR_SIZE, rfd.sector_map[i])
					!= SECTOR_SIZE) {
				perror(rfd.mtd_filename);
				goto err;
			}
		}

		if (write(out_fd, sector, SECTOR_SIZE) != SECTOR_SIZE) {
			perror(rfd.out_filename);
			goto err;
		}
	}

	if (rfd.verbose)
		printf("Copied %d sectors (%d blank)\n", rfd.sector_count, blank);

	close(out_fd);
	close(fd);
	free(rfd.header);
	free(rfd.sector_map);

	return 0;

err:
	if (out_fd)
		close(out_fd);

	close(fd);
	free(rfd.header);
	free(rfd.sector_map);

	return 2;
}

