/* $NetBSD: iplsum.c,v 1.2 2015/12/13 18:38:23 christos Exp $ */ /* * Calculate 32bit checksum of IPL and store in a certain location * * Written in 2003 by ITOH Yasufumi. * Public domain */ #include #include #include #include #ifndef __BIT_TYPES_DEFINED__ typedef unsigned int uint32_t; #endif /* see README.ipl */ #define IPLOFF (4*1024) /* 4KB */ #define IPL1SIZE (4*1024) /* 4KB */ #define IPL2SIZE (1*1024) /* 1KB */ #define IPL2ONDISK 0x0400 #define IPL3SIZE (3*512) /* 1.5KB */ #define IPL3ONDISK 0x0A00 #define IPLSIZE (IPL1SIZE + IPL2SIZE + IPL3SIZE) #define BOOTSIZE (IPLOFF + IPLSIZE) #define BOOTBLOCKSIZE 8192 uint32_t bootblk[BOOTSIZE / sizeof(uint32_t) + 1]; #define SUMOFF ((IPLOFF + 4) / sizeof(uint32_t)) #ifdef __STDC__ int main(int, char *[]); #endif int main(int argc, char *argv[]) { FILE *fp; int len; uint32_t sum, *p; int iploff, iplsumsize; if (argc != 3) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } /* read file */ if ((fp = fopen(argv[1], "rb")) == NULL) { perror(argv[1]); return 1; } if ((len = fread(bootblk, 1, sizeof bootblk, fp)) <= IPLOFF) { fclose(fp); fprintf(stderr, "%s: too short\n", argv[1]); return 1; } else if (len > BOOTSIZE) { fclose(fp); fprintf(stderr, "%s: too long (%d vs %d)\n", argv[1], len, BOOTSIZE); return 1; } (void) fclose(fp); /* sanity check */ if ((ntohl(bootblk[0]) & 0xffff0000) != 0x80000000) { fprintf(stderr, "%s: bad LIF magic\n", argv[1]); return 1; } iploff = ntohl(bootblk[0xf0 / sizeof(uint32_t)]); iplsumsize = ntohl(bootblk[0xf4 / sizeof(uint32_t)]); printf("%d bytes free, ipl offset = %d, ipl sum size = %d\n", BOOTSIZE - len, iploff, iplsumsize); if (iploff != IPLOFF || iplsumsize <= 0 || iplsumsize % 2048 || iploff + iplsumsize > BOOTBLOCKSIZE) { fprintf(stderr, "%s: bad ipl offset / size\n", argv[1]); return 1; } /* checksum */ sum = 0; for (p = bootblk + IPLOFF / sizeof(uint32_t); p < bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t); p++) sum += ntohl(*p); bootblk[SUMOFF] = htonl(ntohl(bootblk[SUMOFF]) - sum); /* transfer ipl part 2 */ memcpy(bootblk + IPL2ONDISK / sizeof(uint32_t), bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t), IPL2SIZE); /* transfer ipl part 3 */ memcpy(bootblk + IPL3ONDISK / sizeof(uint32_t), bootblk + (IPLOFF + IPL1SIZE + IPL2SIZE) / sizeof(uint32_t), IPL3SIZE); /* write file */ if ((fp = fopen(argv[2], "wb")) == NULL) { perror(argv[2]); return 1; } if ((len = fwrite(bootblk, 1, BOOTBLOCKSIZE, fp)) != BOOTBLOCKSIZE) { if (len < 0) perror(argv[2]); else fprintf(stderr, "%s: short write\n", argv[2]); fclose(fp); (void) remove(argv[2]); return 1; } if (fclose(fp)) { perror(argv[2]); (void) remove(argv[2]); return 1; } return 0; }