/*
 * ROMBurst 1.0: Tease apart the contents of a Zaurus 16MB ROM image.
 * Last update: 20020619
 *
 * Copyright 2002 Ian Goldberg <ian@cypherpunks.ca>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#define ROMSIZE (16<<20)

#pragma pack(1)
struct dnt {
    char filename[8];
    char fileext[3];
    char unused[5];
    char date[8];
    unsigned int start;
    unsigned int end;
};
#pragma pack()

int main(int argc, char **argv)
{
    int rfd, res, i;
    unsigned char *rommem;
    struct stat st;
    struct dnt *directory;

    if (argc != 2) {
	fprintf(stderr, "Usage: %s romfile\n", argv[0]);
	exit(1);
    }

    rfd = open(argv[1], O_RDONLY);
    if (rfd < 0) {
	perror("open");
	exit(1);
    }

    res = fstat(rfd, &st);
    if (res < 0) {
	perror("fstat");
	exit(1);
    }

    if (st.st_size != ROMSIZE) {
	fprintf(stderr, "ROM file must be %d bytes long.\n", ROMSIZE);
	exit(1);
    }

    rommem = mmap(NULL, ROMSIZE, PROT_READ, MAP_SHARED, rfd, 0);
    if (rommem == MAP_FAILED) {
	perror("mmap");
	exit(1);
    }

    directory = (struct dnt*)(rommem+0xff8000);

    for(i=0;;++i) {
	int j;
	FILE *pf;
	char fname[8+1+3+1+8+1];
	char *p = fname;

	if (!strncmp(directory[i].filename, "END     ", 8)) {
	    break;
	}
	printf("%.8s.%.3s %.8s %08x %08x\n",
		directory[i].filename,
		directory[i].fileext,
		directory[i].date,
		directory[i].start,
		directory[i].end);
	/* Make a real filename */
	strncpy(p, directory[i].filename, 8);
	for(j=0;j<8;++j) {
	    if (*p == '\0' || *p == ' ') break;
	    ++p;
	}
	if (directory[i].fileext[0] != ' ') {
	    *p++ = '.';
	    strncpy(p, directory[i].fileext, 3);
	    for(j=0;j<3;++j) {
		if (*p == '\0' || *p == ' ') break;
		++p;
	    }
	}
	*p++ = '-';
	strncpy(p, directory[i].date, 8);
	for(j=0;j<8;++j) {
	    if (*p == '\0' || *p == ' ') break;
	    ++p;
	}
	*p = '\0';

	/* And write the file */
	pf = fopen(fname, "w");
	if (!pf) {
	    perror("fopen");
	    exit(1);
	}
	fwrite(rommem+directory[i].start, directory[i].end-directory[i].start,
		1, pf);
	fclose(pf);
    }

    munmap(rommem, ROMSIZE);
    return 0;
}

