view miscprog/grokdsn.c @ 191:0c631396b8ce

started grokdsn utility, parses header successfully
author Michael Spacefalcon <falcon@ivan.Harhan.ORG>
date Wed, 07 Jan 2015 06:55:33 +0000
parents
children 5d84f63eff72
line wrap: on
line source

/*
 * We have TI's Leonardo reference schematics in the form of 3 different PDF
 * versions and an OrCAD DSN file corresponding to one of them.  The latter
 * appears (based on a cursory strings(1) inspection) to contain more
 * juicy information than is present in the PDF prints.  We need to extract
 * as much of this information as we can in order to replicate the lost
 * Leonardo board as closely as possible.
 *
 * The top level structure of this DSN file appears to be Microsoft CDF.
 * Therefore, I shall begin by parsing this "archive" structure and
 * extracting the individual files contained therein, in an effort to gain
 * more insight as to what goes with what than can be gleaned from strings(1)
 * on the raw DSN file.  This hack-utility is my CDF parser written for
 * this specific purpose.
 */

#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdint.h>
#include <endian.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>

#define	HEADER_MFAT_ENTRIES	109
struct cdf_header {
	u_char		magic[8];
	u_char		uid[16];
	uint16_t	fmt_minor;
	uint16_t	fmt_major;
	uint16_t	byte_order;
	uint16_t	sector_size;
	uint16_t	subsec_size;
	u_char		rsvd1[10];
	uint32_t	fat_sectors;
	uint32_t	dir_start;
	u_char		rsvd2[4];
	uint32_t	min_large_file;
	uint32_t	subfat_start;
	uint32_t	subfat_sectors;
	uint32_t	mfat_start;
	uint32_t	mfat_sectors;
	uint32_t	fat_secids[HEADER_MFAT_ENTRIES];
};

char *dsnfilename;
u_char *filemapping;
struct cdf_header *cdf_header;
unsigned total_sectors;

open_and_mmap_file()
{
	int fd;
	struct stat st;

	fd = open(dsnfilename, O_RDONLY);
	if (fd < 0) {
		perror(dsnfilename);
		exit(1);
	}
	fstat(fd, &st);
	if (!S_ISREG(st.st_mode)) {
		fprintf(stderr, "error: %s is not a regular file\n",
			dsnfilename);
		exit(1);
	}
	if (st.st_size < 512) {
		fprintf(stderr, "error: %s is shorter than 512 bytes\n",
			dsnfilename);
		exit(1);
	}
	if (st.st_size % 512) {
		fprintf(stderr, "error: %s is not a multiple of 512 bytes\n",
			dsnfilename);
		exit(1);
	}
	filemapping = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (filemapping == MAP_FAILED) {
		perror("mmap");
		exit(1);
	}
	close(fd);
	cdf_header = (struct cdf_header *) filemapping;
	total_sectors = st.st_size / 512 - 1;
	return(0);
}

dump_cdf_header()
{
	printf("Magic: %02X %02X %02X %02X %02X %02X %02X %02X\n",
		cdf_header->magic[0], cdf_header->magic[1],
		cdf_header->magic[2], cdf_header->magic[3],
		cdf_header->magic[4], cdf_header->magic[5],
		cdf_header->magic[6], cdf_header->magic[7]);
	printf("Format version: %04X.%04X\n", le16toh(cdf_header->fmt_major),
		le16toh(cdf_header->fmt_minor));
	printf("Sector / subsector shift: %u / %u\n",
		le16toh(cdf_header->sector_size),
		le16toh(cdf_header->subsec_size));
	printf("Total FAT sectors: %u\n", le32toh(cdf_header->fat_sectors));
	printf("Directory start sector: %u\n", le32toh(cdf_header->dir_start));
	printf("File size threshold: %u\n",
		le32toh(cdf_header->min_large_file));
	return(0);
}

main(argc, argv)
	char **argv;
{
	if (sizeof(struct cdf_header) != 512) {
		fprintf(stderr, "error: struct cdf_header is misdefined\n");
		exit(1);
	}
	if (argc != 3) {
		fprintf(stderr, "usage: %s binfile.dsn <operation>\n", argv[0]);
		exit(1);
	}
	dsnfilename = argv[1];
	open_and_mmap_file();
	if (!strcmp(argv[2], "hdr"))
		return dump_cdf_header();
	fprintf(stderr, "error: \"%s\" is not a recognized command\n", argv[2]);
	exit(1);
}