makemask.c 2.64 KB
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "boot_image.h"

#define min2(a, b) ( (a)<(b) ? (a) : (b) )
int swapped;

#define CKSUM_START 0x1000
#define CKSUM_LENGTH 0x100000
#define CKSUM_END (CKSUM_START + CKSUM_LENGTH)

#define CKSUM_STARTVAL 0xf8ca4ddc

#define ROL(i, b) (((i)<<(b)) | ((i)>>(32-(b))))

#define L2B(l, b, s)  (b)[0^(s)] = ((l)>>24)&0xff; \
                             (b)[1^(s)] = ((l)>>16)&0xff; \
                             (b)[2^(s)] = ((l)>> 8)&0xff; \
                             (b)[3^(s)] = ((l)    )&0xff;

#define HEADER_MAGIC 0x80371240

void
calc3(FILE *f, char* name, unsigned char hash[]) {
    unsigned char buf[32768];
    unsigned long sum1, sum2;
    unsigned long len;
    unsigned long i;
    unsigned long c1, k1, k2;
    unsigned long t1, t2, t3, t4, t5, t6;
    unsigned int n;
    long clen = CKSUM_LENGTH;
    long left = len - CKSUM_START;

    fseek(f, 0, SEEK_END);
    len = ftell(f);

    if (len < CKSUM_END) {
	if (len < CKSUM_START) {
	    fprintf(stderr, "%s: is too short to checksum\n", name);
	    exit(1);
	} else if ( (len & 3) != 0 ) {
	    fprintf(stderr, "%s: length isn't a multiple of 4 bytes\n", name);
	    exit(1);
	}
    }

    fseek(f, CKSUM_START, SEEK_SET);
    t1 = t2 = t3 = t4 = t5 = t6 = CKSUM_STARTVAL;

    clen = CKSUM_LENGTH;
    left = len - CKSUM_START;
    while(clen > 0) {
	n = fread(buf, 1, clen < sizeof buf ? clen: sizeof buf, f);
	if ( (n == 0) || ((n&3) != 0) ) {
	    if ( (clen != 0) || (n != 0) ){
		fprintf(stderr, "%s: short read\n", name);
		exit(1);
	    }
	}

	for ( i = 0 ; i < n ; i += 4 ) {
	    c1 = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
	    k1 = t6 + c1;
	    if (k1 < t6) t4++;
	    t6 = k1;
	    t3 ^= c1;
	    k2 = c1 & 0x1f;
	    k1 = ROL(c1, k2);
	    t5 += k1;
	    if (c1 < t2) {
		t2 ^= k1;
	    } else {
		t2 ^= t6 ^ c1;
	    }
	    t1 += c1 ^ t5;
	}
	left -= n;
	clen -= n;
    }
    sum1 = t6 ^ t4 ^ t3;
    sum2 = t5 ^ t2 ^ t1;

    hash[0] = sum1 >> 24;
    hash[1] = sum1 >> 16;
    hash[2] = sum1 >> 8;
    hash[3] = sum1;
    hash[4] = sum2 >> 24;
    hash[5] = sum2 >> 16;
    hash[6] = sum2 >> 8;
    hash[7] = sum2;
}

int
main(int argc, char* argv[]) {
    FILE* fp;
    unsigned char hash[8];
    if (argc != 2) {
	fprintf(stderr, "Usage: makemask rom\n");
	return 1;
    }

    if ((fp = fopen(argv[1], "r+b")) == 0) {
	perror(argv[1]);
	return 1;
    }

    /* compute hash */
    calc3(fp, argv[1], hash);

    /* write hash */
    fseek(fp, 16, SEEK_SET);
    fwrite(hash, sizeof hash, 1, fp);

    /* add bootstrap code */
    fseek(fp, 64, SEEK_SET);
    fwrite(boot_image, 1, 4032, fp);
    fclose(fp);
    return 0;
}