xref: /netbsd-src/sys/arch/hppa/stand/xxboot/iplsum.c (revision 23d819855e6f3831b470936daf0a8622474d0018)
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
main(int argc,char * argv[])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