Home | History | Annotate | Line # | Download | only in xxboot
      1 /*	$NetBSD: iplsum.c,v 1.2 2015/12/13 18:38:23 christos Exp $	*/
      2 
      3 /*
      4  * Calculate 32bit checksum of IPL and store in a certain location
      5  *
      6  * Written in 2003 by ITOH Yasufumi.
      7  * Public domain
      8  */
      9 
     10 #include <sys/types.h>
     11 #include <stdio.h>
     12 #include <string.h>
     13 #include <netinet/in.h>
     14 
     15 #ifndef __BIT_TYPES_DEFINED__
     16 typedef unsigned int	uint32_t;
     17 #endif
     18 
     19 /* see README.ipl */
     20 #define IPLOFF		(4*1024)	/* 4KB */
     21 #define IPL1SIZE	(4*1024)	/* 4KB */
     22 #define IPL2SIZE	(1*1024)	/* 1KB */
     23 #define IPL2ONDISK	0x0400
     24 #define IPL3SIZE	(3*512)		/* 1.5KB */
     25 #define IPL3ONDISK	0x0A00
     26 #define IPLSIZE		(IPL1SIZE + IPL2SIZE + IPL3SIZE)
     27 #define BOOTSIZE	(IPLOFF + IPLSIZE)
     28 #define BOOTBLOCKSIZE	8192
     29 
     30 uint32_t bootblk[BOOTSIZE / sizeof(uint32_t) + 1];
     31 
     32 #define SUMOFF		((IPLOFF + 4) / sizeof(uint32_t))
     33 
     34 #ifdef __STDC__
     35 int main(int, char *[]);
     36 #endif
     37 
     38 int
     39 main(int argc, char *argv[])
     40 {
     41 	FILE *fp;
     42 	int len;
     43 	uint32_t sum, *p;
     44 	int iploff, iplsumsize;
     45 
     46 	if (argc != 3) {
     47 		fprintf(stderr, "usage: %s <input> <output>\n", argv[0]);
     48 		return 1;
     49 	}
     50 
     51 	/* read file */
     52 	if ((fp = fopen(argv[1], "rb")) == NULL) {
     53 		perror(argv[1]);
     54 		return 1;
     55 	}
     56 	if ((len = fread(bootblk, 1, sizeof bootblk, fp)) <= IPLOFF) {
     57 		fclose(fp);
     58 		fprintf(stderr, "%s: too short\n", argv[1]);
     59 		return 1;
     60 	} else if (len > BOOTSIZE) {
     61 		fclose(fp);
     62 		fprintf(stderr, "%s: too long (%d vs %d)\n", argv[1], len, BOOTSIZE);
     63 		return 1;
     64 	}
     65 	(void) fclose(fp);
     66 
     67 	/* sanity check */
     68 	if ((ntohl(bootblk[0]) & 0xffff0000) != 0x80000000) {
     69 		fprintf(stderr, "%s: bad LIF magic\n", argv[1]);
     70 		return 1;
     71 	}
     72 	iploff = ntohl(bootblk[0xf0 / sizeof(uint32_t)]);
     73 	iplsumsize = ntohl(bootblk[0xf4 / sizeof(uint32_t)]);
     74 	printf("%d bytes free, ipl offset = %d, ipl sum size = %d\n",
     75 	    BOOTSIZE - len, iploff, iplsumsize);
     76 	if (iploff != IPLOFF || iplsumsize <= 0 || iplsumsize % 2048 ||
     77 	    iploff + iplsumsize > BOOTBLOCKSIZE) {
     78 		fprintf(stderr, "%s: bad ipl offset / size\n", argv[1]);
     79 		return 1;
     80 	}
     81 
     82 	/* checksum */
     83 	sum = 0;
     84 	for (p = bootblk + IPLOFF / sizeof(uint32_t);
     85 	    p < bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t); p++)
     86 		sum += ntohl(*p);
     87 
     88 	bootblk[SUMOFF] = htonl(ntohl(bootblk[SUMOFF]) - sum);
     89 
     90 	/* transfer ipl part 2 */
     91 	memcpy(bootblk + IPL2ONDISK / sizeof(uint32_t),
     92 	    bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t),
     93 	    IPL2SIZE);
     94 
     95 	/* transfer ipl part 3 */
     96 	memcpy(bootblk + IPL3ONDISK / sizeof(uint32_t),
     97 	    bootblk + (IPLOFF + IPL1SIZE + IPL2SIZE) / sizeof(uint32_t),
     98 	    IPL3SIZE);
     99 
    100 	/* write file */
    101 	if ((fp = fopen(argv[2], "wb")) == NULL) {
    102 		perror(argv[2]);
    103 		return 1;
    104 	}
    105 	if ((len = fwrite(bootblk, 1, BOOTBLOCKSIZE, fp)) != BOOTBLOCKSIZE) {
    106 		if (len < 0)
    107 			perror(argv[2]);
    108 		else
    109 			fprintf(stderr, "%s: short write\n", argv[2]);
    110 		fclose(fp);
    111 		(void) remove(argv[2]);
    112 		return 1;
    113 	}
    114 	if (fclose(fp)) {
    115 		perror(argv[2]);
    116 		(void) remove(argv[2]);
    117 		return 1;
    118 	}
    119 
    120 	return 0;
    121 }
    122