view miscprog/pircksum2.c @ 251:6d9a6627b085

pirelli/fw-disasm: continuing Switch_ON() analysis
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 Dec 2017 18:03:25 +0000
parents d69f7512e3c1
children
line wrap: on
line source

/*
 * This program verifies the correctness of the understanding described in the
 * ../pirelli/flash2-chksum write-up.
 */

#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>

char *image_filename;
u_char *image_map, *endrec;
unsigned imgsize, max_imgsize;

open_and_map_file()
{
	int fd;
	struct stat st;

	fd = open(image_filename, O_RDONLY);
	if (fd < 0) {
		perror(image_filename);
		exit(1);
	}
	fstat(fd, &st);
	if (!S_ISREG(st.st_mode)) {
		fprintf(stderr, "error: %s is not a regular file\n",
			image_filename);
		exit(1);
	}
	if (st.st_size != 0x10000 && st.st_size != 0x360000) {
		fprintf(stderr, "error: %s has an unexpected size\n",
			image_filename);
		exit(1);
	}
	max_imgsize = st.st_size - 12;
	image_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (image_map == MAP_FAILED) {
		perror("mmap");
		exit(1);
	}
	close(fd);
	endrec = image_map + max_imgsize;
	return 0;
}

verify_chksum1()
{
	uint16_t sum, ref;
	unsigned offset;

	sum = 0;
	for (offset = 0; offset + 1 < imgsize; offset += 2)
		sum += le16toh(*(uint16_t *)(image_map + offset));
	if (imgsize & 1)
		sum += image_map[offset];
	ref = le16toh(*(uint16_t *)(endrec + 8));
	if (sum == ref) {
		printf("Checksum 1 matches (%04X)\n", sum);
		return 0;
	} else {
		printf("Checksum 1 FAILED: computed %04X, stored %04X\n",
			sum, ref);
		return 1;
	}
}

verify_chksum2()
{
	uint16_t sum, ref;
	unsigned offset;

	sum = 0;
	for (offset = 0; offset < 10; offset += 2)
		sum += le16toh(*(uint16_t *)(endrec + offset));
	ref = le16toh(*(uint16_t *)(endrec + 10));
	if (sum == ref) {
		printf("Checksum 2 matches (%04X)\n", sum);
		return 0;
	} else {
		printf("Checksum 2 FAILED: computed %04X, stored %04X\n",
			sum, ref);
		return 1;
	}
}

main(argc, argv)
	char **argv;
{
	int stat1, stat2;

	if (argc != 2) {
		fprintf(stderr, "usage: %s image-filename\n", argv[0]);
		exit(1);
	}
	image_filename = argv[1];
	open_and_map_file();
	if (le32toh(*(uint32_t *)endrec) != 0x12345678) {
		printf("Error: 0x12345678 signature missing\n");
		exit(1);
	}
	imgsize = le32toh(*(uint32_t *)(endrec + 4));
	if (imgsize < 1 || imgsize > max_imgsize) {
		printf("Error: bogus image size of 0x%x bytes\n", imgsize);
		exit(1);
	}
	printf("Image size: 0x%x bytes\n", imgsize);
	stat1 = verify_chksum1();
	stat2 = verify_chksum2();
	exit(stat1 || stat2);
}