1/* $NetBSD$ */ 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__ 16typedef 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 30uint32_t bootblk[BOOTSIZE / sizeof(uint32_t) + 1]; 31 32#define SUMOFF ((IPLOFF + 4) / sizeof(uint32_t)) 33 34#ifdef __STDC__ 35int main(int, char *[]); 36#endif 37 38int 39main(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 fprintf(stderr, "%s: too short\n", argv[1]); 58 return 1; 59 } else if (len > BOOTSIZE) { 60 fprintf(stderr, "%s: too long\n", argv[1]); 61 return 1; 62 } 63 (void) fclose(fp); 64 65 /* sanity check */ 66 if ((ntohl(bootblk[0]) & 0xffff0000) != 0x80000000) { 67 fprintf(stderr, "%s: bad LIF magic\n", argv[1]); 68 return 1; 69 } 70 iploff = ntohl(bootblk[0xf0 / sizeof(uint32_t)]); 71 iplsumsize = ntohl(bootblk[0xf4 / sizeof(uint32_t)]); 72 printf("%d bytes free, ipl offset = %d, ipl sum size = %d\n", 73 BOOTSIZE - len, iploff, iplsumsize); 74 if (iploff != IPLOFF || iplsumsize <= 0 || iplsumsize % 2048 || 75 iploff + iplsumsize > BOOTBLOCKSIZE) { 76 fprintf(stderr, "%s: bad ipl offset / size\n", argv[1]); 77 return 1; 78 } 79 80 /* checksum */ 81 sum = 0; 82 for (p = bootblk + IPLOFF / sizeof(uint32_t); 83 p < bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t); p++) 84 sum += ntohl(*p); 85 86 bootblk[SUMOFF] = htonl(ntohl(bootblk[SUMOFF]) - sum); 87 88 /* transfer ipl part 2 */ 89 memcpy(bootblk + IPL2ONDISK / sizeof(uint32_t), 90 bootblk + (IPLOFF + IPL1SIZE) / sizeof(uint32_t), 91 IPL2SIZE); 92 93 /* transfer ipl part 3 */ 94 memcpy(bootblk + IPL3ONDISK / sizeof(uint32_t), 95 bootblk + (IPLOFF + IPL1SIZE + IPL2SIZE) / sizeof(uint32_t), 96 IPL3SIZE); 97 98 /* write file */ 99 if ((fp = fopen(argv[2], "wb")) == NULL) { 100 perror(argv[2]); 101 return 1; 102 } 103 if ((len = fwrite(bootblk, 1, BOOTBLOCKSIZE, fp)) != BOOTBLOCKSIZE) { 104 if (len < 0) 105 perror(argv[2]); 106 else 107 fprintf(stderr, "%s: short write\n", argv[2]); 108 fclose(fp); 109 (void) remove(argv[2]); 110 return 1; 111 } 112 if (fclose(fp)) { 113 perror(argv[2]); 114 (void) remove(argv[2]); 115 return 1; 116 } 117 118 return 0; 119} 120