summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/stand/openbsd/sboot/srec.c
blob: 164fb4b458c615e1254b98989959bc82708b14d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Public domain, believed to be by Mike Price.
 * 
 * convert binary file to Srecord format
 * XXX srec generates improper checksums for 4-byte dumps
 */
#include <stdio.h>
#include <ctype.h>

int get32();
void put32();
void sput();
void put();
int checksum();

int mask;
int size;

main(argc, argv)
	int argc;
	char *argv[];
{
	char buf[32];
	int cc;
	int base;
	int addr;
	char *name;

	if (argc != 4) {
		fprintf(stderr, "usage: %s {size} {hex_addr} {name}\n", argv[0]);
		fprintf(stderr, "Size = 2, 3, or 4 byte address\n");
		exit(1);
	}
	sscanf(argv[1], "%x", &size);
	mask = (1 << (size * 8)) - 1;
	if (!mask)
		mask = (-1);
	sscanf(argv[2], "%x", &base);
	name = argv[3];

	if (size == 2)
		printf("S0%02X%04X", 2 + strlen(name) + 1, 0);
	if (size == 3)
		printf("S0%02X%06X", 3 + strlen(name) + 1, 0);
	if (size == 4)
		printf("S0%02X%08X", 4 + strlen(name) + 1, 0);
	sput(name);
	printf("%02X\n", checksum(0, name, strlen(name), size));

	addr = base;
	for (;;) {
		cc = get32(buf);
		if (cc > 0) {
			put32(cc, addr, buf, size, mask);
			addr += cc;
		} else
			break;
	}

	buf[0] = base >> 8;
	buf[1] = base;
	printf("S%d%02X", 11 - size, 2 + 1);
	switch (size) {
	case 2:
		printf("%04X", base & mask);
		break;
	case 3:
		printf("%06X", base & mask);
		break;
	case 4:
		printf("%08X", base & mask);
		break;
	}

	/*
	 * kludge -> don't know why you have to add the +1 = works
	 * for size =3 at least
	 */
	printf("%02X\n", checksum(base, (char *) 0, 0, size) + 1);
	exit (0);
}

int
get32(buf)
	char buf[];
{
	char *cp = buf;
	int i;
	int c;

	for (i = 0; i < 32; ++i) {
		if ((c = getchar()) != EOF)
			*cp++ = c;
		else
			break;
	}
	return (cp - buf);
}

void
put32(len, addr, buf, size, mask)
	int len;
	int addr;
	char buf[];
	int size, mask;
{
	char *cp = buf;
	int i;

	if (size == 2)
		printf("S1%02X%04X", 2 + len + 1, addr & mask);
	if (size == 3)
		printf("S2%02X%06X", 3 + len + 1, addr & mask);
	if (size == 4)
		printf("S3%02X%08X", 4 + len + 1, addr & mask);
	for (i = 0; i < len; ++i)
		put(*cp++);
	printf("%02X\n", checksum(addr, buf, len, size));
}

void
sput(s)
	char *s;
{
	while (*s != '\0')
		put(*s++);
}

void
put(c)
	int c;
{
	printf("%02X", c & 0xff);
}

int
checksum(addr, buf, len, size)
	int addr;
	char buf[];
	int len;
	int size;
{
	char *cp = buf;
	int sum = 0xff - 1 - size - (len & 0xff);
	int i;

	if (size == 4)
		sum -= (addr >> 24) & 0xff;
	if (size >= 3)
		sum -= (addr >> 16) & 0xff;
	sum -= (addr >> 8) & 0xff;
	sum -= addr & 0xff;
	for (i = 0; i < len; ++i) {
		sum -= *cp++ & 0xff;
	}
	return (sum & 0xff);
}