xref: /netbsd-src/sys/arch/hppa/stand/xxboot/iplsum.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: iplsum.c,v 1.1 2014/02/24 07:23:43 skrll 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 		fprintf(stderr, "%s: too short\n", argv[1]);
58 		return 1;
59 	} else if (len > BOOTSIZE) {
60 		fprintf(stderr, "%s: too long (%d vs %d)\n", argv[1], len, BOOTSIZE);
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